Java tutorial
/* Copyright 2008-2014 ITACA-TSB, http://www.tsb.upv.es Instituto Tecnologico de Aplicaciones de Comunicacion Avanzadas - Grupo Tecnologias para la Salud y el Bienestar (TSB) See the NOTICE file distributed with this work for additional information regarding copyright ownership Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.universAAL.android.services; import java.util.Dictionary; import java.util.Hashtable; import org.universAAL.android.R; import org.universAAL.android.activities.HandlerActivity; import org.universAAL.android.container.AndroidContainer; import org.universAAL.android.container.AndroidContext; import org.universAAL.android.container.AndroidRegistry; import org.universAAL.android.handler.AndroidHandler; import org.universAAL.android.utils.Config; import org.universAAL.android.utils.GroundingParcel; import org.universAAL.android.utils.AppConstants; import org.universAAL.android.utils.RAPIManager; import org.universAAL.android.wrappers.CommunicationConnectorWrapper; import org.universAAL.android.wrappers.DiscoveryConnectorWrapper; import org.universAAL.middleware.brokers.control.ControlBroker; import org.universAAL.middleware.bus.model.AbstractBus; import org.universAAL.middleware.bus.msg.BusMessage; import org.universAAL.middleware.connectors.CommunicationConnector; import org.universAAL.middleware.connectors.DiscoveryConnector; import org.universAAL.middleware.connectors.communication.jgroups.JGroupsCommunicationConnector; import org.universAAL.middleware.connectors.discovery.slp.SLPDiscoveryConnector; import org.universAAL.middleware.container.ModuleContext; import org.universAAL.middleware.context.ContextBus; import org.universAAL.middleware.context.impl.ContextBusImpl; import org.universAAL.middleware.datarep.SharedResources; import org.universAAL.middleware.interfaces.PeerCard; import org.universAAL.middleware.interfaces.aalspace.AALSpaceDescriptor; import org.universAAL.middleware.interfaces.aalspace.AALSpaceStatus; import org.universAAL.middleware.managers.aalspace.AALSpaceManagerImpl; import org.universAAL.middleware.managers.api.AALSpaceEventHandler; import org.universAAL.middleware.managers.api.AALSpaceListener; import org.universAAL.middleware.managers.api.AALSpaceManager; import org.universAAL.middleware.modules.AALSpaceModule; import org.universAAL.middleware.modules.CommunicationModule; import org.universAAL.middleware.modules.aalspace.AALSpaceModuleImpl; import org.universAAL.middleware.modules.communication.CommunicationModuleImpl; import org.universAAL.middleware.serialization.MessageContentSerializer; import org.universAAL.middleware.serialization.MessageContentSerializerEx; import org.universAAL.middleware.serialization.turtle.TurtleSerializer; import org.universAAL.middleware.serialization.turtle.TurtleUtil; import org.universAAL.middleware.service.ServiceBus.CallInjector; import org.universAAL.middleware.service.impl.ServiceBusImpl; import org.universAAL.middleware.tracker.IBusMemberRegistry; import org.universAAL.middleware.tracker.impl.BusMemberRegistryImpl; import org.universAAL.middleware.ui.IUIBus; import org.universAAL.middleware.ui.impl.UIBusImpl; import org.universAAL.middleware.util.Constants; import org.universAAL.ri.gateway.Gateway; import ch.ethz.iks.slp.Advertiser; import ch.ethz.iks.slp.Locator; import ch.ethz.iks.slp.impl.AdvertiserImpl; import ch.ethz.iks.slp.impl.LocatorImpl; import ch.ethz.iks.slp.impl.SLPCore; import android.annotation.SuppressLint; import android.app.Notification; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.MulticastLock; import android.os.Build; import android.os.Environment; import android.os.IBinder; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.util.Log; //import android.widget.Toast; /** * Central class and service of the application. It takes care of starting and * stopping the middleware, while maintaining in memory, as local variables, * each module of the middleware. It handles the different messages, sent as * intents, that are received to identify the different operations and stages of * the middleware. * * @author alfiva * */ public class MiddlewareService extends Service implements AALSpaceListener { private static final String TAG = "MiddlewareService"; private static final String TAG_THREAD_CREATE = "MW Service Create"; private static final String TAG_THREAD_START = "MW Service Start"; private static final String TAG_THREAD_UI = "UI Handler Create"; private static final int ONGOING_NOTIFICATION = 3948234; // TODO Random one? private static int mCurrentWIFI = AppConstants.WIFI_OFF; // This is for the previous state of WIFI public static int mUserType = AppConstants.USER_TYPE_AP; // Just default but it is here to get it from AndroidHandler public static int mPercentage = 0; // This is for the progress bar private MulticastLock mLock; // MW modules stay in memory in this service class (Container holds only WeakRefs) private Advertiser mJSLPadvertiser; private Locator mJSLPlocator; private CommunicationConnector mModJGROUPS; private DiscoveryConnector mModJSLP; private CommunicationModuleImpl mModCOMMUNICATION; private AALSpaceManagerImpl mModSPACEMANAGER; private AALSpaceModuleImpl mModSPACEMODULE; private ControlBroker mModCONTROLBROKER; private TurtleSerializer mModSERIALIZER; private BusMemberRegistryImpl mModTRACKER; private Gateway mModGATEWAY; private AndroidHandler mModHANDLER; @Override public void onCreate() { // This is where MW is created as it is called once when service is instantiated. Make sure it runs forever. super.onCreate(); Log.v(TAG, "Create"); mPercentage = 0; // Ongoing notification is mandatory after Android 4.0 Intent notificationIntent = new Intent(this, HandlerActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK); NotificationCompat.Builder builder = new NotificationCompat.Builder(this).setSmallIcon(R.drawable.ic_notif) .setContentTitle(getString(R.string.notif_title)).setContentText(getString(R.string.notif_text)) .setContentIntent(contentIntent).setPriority(NotificationCompat.PRIORITY_MIN); Notification notif = builder.build(); notif.flags |= Notification.FLAG_NO_CLEAR; startForeground(ONGOING_NOTIFICATION, notif); //Load initial config through Config utility. Changing config requires restart the MW service to take effect. Config.load(getApplicationContext()); // These properties must be set here, not from file System.setProperty("java.net.preferIPv4Stack", "true"); System.setProperty("java.net.preferIPv6Stack", "false"); System.setProperty("java.net.preferIPv4Addresses", "true"); System.setProperty("java.net.preferIPv6Addresses", "false"); System.setProperty("jgroups.use.jdk_logger ", "true"); System.setProperty("net.slp.port", "5555"); System.setProperty("org.universAAL.middleware.peer.is_coordinator", Boolean.toString(Config.isServiceCoord())); // This is for setting IP manually, just in case (set it everytime you // get a new IP). If not set, it seems it also works, but SLP keeps // working on multicast for a while after Wifi is turned off. // System.setProperty("net.slp.interfaces", "192.168.0.126"); // This is for not blocking the sockets when reconnecting (check its // javadoc). Common sense would suggest to set it false, but it still // works without doing so. // System.setProperty("http.keepAlive", "false"); // Google had the wonderful idea in Android 5.0 of not enabling WIFI // connection when it does not have internet access, and fall back to // data connection. So in 5.0 we have to deliberately request WIFI and // set it as the process connection when it "becomes" available. And // pray that WIFI is ON by the time we make our checks... if (Config.isWifiAllowed()) { requestLollipopWifi(); } // Create (dont use yet) the multicast lock. Make it not counted: this app only uses one lock WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE); mLock = wifi.createMulticastLock("uaal_multicast"); mLock.setReferenceCounted(false); // Set the static platform of SLP (for logging and stuff). Do it here cause its static (!) SLPCore.platform = AndroidContext.THE_CONTEXT; // Start the MW! Put all the above inside thread too? Cmon, its fast! Also, notification must be there new Thread(new Runnable() { public void run() { // Start the MW in onCreate makes sure it is running before // handling any intents. The only problem is when stopping the // MW and an intent comes... TODO addPercent(1); mCurrentWIFI = checkWifi();//Set the initial status of WIFI // 1. Stop-start the connector modules. Use jSLP only IF WIFI enabled, and WIFI==WIFI_HOME or WIFI_NOT_SET if (Config.isWifiAllowed() && (mCurrentWIFI == AppConstants.WIFI_HOME || mCurrentWIFI == AppConstants.WIFI_NOTSET)) { restartConnector(true); } else { restartConnector(false); } // 2. Start the MW modules startMiddleware(); // 3. Register the ontologies // It appears ont service does run in separate thread > race cond: AP ont may not be reg before handler // That is why I moved to a static method instead of ACTION_ONT_REG_ALL intent TODO retrofit OntologyService OntologyService.registerOntologies(MiddlewareService.this); addPercent(25); // 4. Start UI handler TODO start handler in last place if (Config.isUIHandler()) { startHandler(); } else { addPercent(5);//startHandler() adds 5 when finished } // 5. Start GW IF WIFI==NOT_ON or WIFI==STRANGER (or if ALWAYS) if (isGWrequired()) { startGateway(); } addPercent(10); // 6. Register the apps Intent scan = new Intent(AppConstants.ACTION_PCK_REG_ALL); scan.setClass(MiddlewareService.this, ScanService.class); startService(scan); } }, TAG_THREAD_CREATE).start(); Log.v(TAG, "Created"); } @Override public void onDestroy() { // Stop and release everything instantiated in onCreate an die. Unshare everything. super.onDestroy(); Log.v(TAG, "Destroy"); //TODO Call to unreg onts? really? mPercentage = 0; notifyPercent(); try { // ScanService ran and tried to stop in parallel while MiddlewareService // has already finished (next lines) AND also sent intents to it which // restarted it. Instead of ACTION_PCK_UNREG_ALL intent I made a method // for this in Registry, since unreg all is a special case (we already // know what to unreg, no need to scan) AndroidRegistry.unregisterAll(); stopGateway(); stopHandler(); stopMiddleware(); stopConnector(); } catch (Exception e) { // HACK: Currently there are bugs in busses stop. Ignoring is not // enough since threads started from the service will not disappear // when the service is killed. Temporary solution is to kill the // whole app process. Log.e(TAG, "Error while destroying service. Will destroy the whole process", e); android.os.Process.killProcess(android.os.Process.myPid()); } Log.v(TAG, "Destroyed"); } @Override public int onStartCommand(final Intent intent, int flags, int startId) { // This will be called each time someone (scan/boot/wifi) sends an intent to this service. Analyze and react accordingly. Log.v(TAG, "Start command: "); // HACK: Set user type for AndroidHandler. Prevents NPE at startup when activity is not visible mUserType = Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(MiddlewareService.this) .getString("setting_type_key", Integer.toString(AppConstants.Defaults.TYPE))); new Thread(new Runnable() { public void run() { if (intent != null) { String action = intent.getAction(); Log.v(TAG, "Intent action: " + action); if (action != null) { if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { //Do nothing, the MW is already started by now in oncreate Log.v(TAG, "Action is BOOT"); } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) || action.equals("android.net.wifi.STATE_CHANGE")) { // Only react to meaningful changes Log.v(TAG, "Action is WIFI"); int newWifi = checkWifi(); //Dont set mCurrentWifi yet, we have to compare if (Config.isWifiAllowed()) { boolean modeGW = (Config.getRemoteMode() == AppConstants.REMOTE_MODE_WIFIOFF); switch (newWifi) { case AppConstants.WIFI_OFF: if (mCurrentWIFI == AppConstants.WIFI_NOTSET || mCurrentWIFI == AppConstants.WIFI_HOME) { if (modeGW) { stopGateway(); } restartConnector(false); // Shut down jSLP, use GW if (modeGW) { startGateway(); } } break; case AppConstants.WIFI_NOTSET: if (mCurrentWIFI == AppConstants.WIFI_OFF || mCurrentWIFI == AppConstants.WIFI_STRANGER) { if (modeGW) { stopGateway(); } restartConnector(true); // Turn on jSLP, dont use GW } break; case AppConstants.WIFI_STRANGER: if (mCurrentWIFI == AppConstants.WIFI_NOTSET || mCurrentWIFI == AppConstants.WIFI_HOME) { if (modeGW) { stopGateway(); } restartConnector(false); // Shut down jSLP, use GW if (modeGW) { startGateway(); } } break; case AppConstants.WIFI_HOME: if (mCurrentWIFI == AppConstants.WIFI_OFF || mCurrentWIFI == AppConstants.WIFI_STRANGER) { if (modeGW) { stopGateway(); } restartConnector(true); // Turn on jSLP, dont use GW } break; default: // Do nothing, keep using jSLP / GW or not, as previous state break; } } mCurrentWIFI = newWifi; } else if (action.equals(AppConstants.ACTION_PCK_REG)) { // REGISTER message from scan service Log.v(TAG, "Action is REGISTER"); AndroidRegistry.register(intent.getStringExtra(AppConstants.ACTION_PCK_REG_X_ID), (GroundingParcel) intent .getParcelableExtra(AppConstants.ACTION_PCK_REG_X_PARCEL), intent.getIntExtra(AppConstants.ACTION_PCK_REG_X_TYPE, 0), MiddlewareService.this); } else if (action.equals(AppConstants.ACTION_PCK_UNREG)) { // UNREGISTER message from scan service Log.v(TAG, "Action is UNREGISTER"); AndroidRegistry.unregister(intent.getStringExtra(AppConstants.ACTION_PCK_UNREG_X_ID), intent.getIntExtra(AppConstants.ACTION_PCK_UNREG_X_TYPE, 0)); } else { // Not the right action yet (TODO check if from receivers) Log.v(TAG, "Action is... Not the right action yet"); } } else { // If (action=null) who? Log.v(TAG, "Action is none"); } } } }, TAG_THREAD_START).start(); return START_STICKY; } @Override public IBinder onBind(Intent arg0) { // Called each time someone asks for our binder to perform operations. I dont use binders anymore. return null; } /** * This makes the connector modules start (And also restarts the AAL Space * Manager). Depending on the parameter passed, it can either start the real * jSLP+jGroups connectors or the fake ones. * * @param connect * Set to true if there is an actual WiFi connection where the * real connectors should be started. Set to false to start the * fake connectors. */ private synchronized void restartConnector(boolean connect) { boolean aalspaceflag = false; // First stop everything related to connector: JSLP, JGroups, Advertiser and Locator // I could use stopConnector() but it is sync, I dont want to change it // TODO Check presence in Container rather than not null? // Stop AALSpaceManager (and GW) to later trigger AALSpace creation, only if it was already started! if (mModSPACEMANAGER != null) { mModSPACEMANAGER.dispose(); AndroidContainer.THE_CONTAINER.removeSharedObjectListener(mModSPACEMANAGER); AndroidContainer.THE_CONTAINER.unshareObject(AALSpaceManager.class.getName(), mModSPACEMANAGER); mModSPACEMANAGER = null; aalspaceflag = true; } if (mModJSLP != null) { try { mModJSLP.dispose(); // -> Exception if wifi off, but must be done } catch (Exception e) { Log.e(TAG, "Could not dispose correctly the JSLP"); } AndroidContainer.THE_CONTAINER.unshareObject(DiscoveryConnector.class.getName(), mModJSLP); mModJSLP = null; } if (mModJGROUPS != null) { try { mModJGROUPS.dispose(); // -> Exception if wifi off, but must be done } catch (Exception e) { Log.e(TAG, "Could not dispose correctly the JGROUPS"); } AndroidContainer.THE_CONTAINER.unshareObject(CommunicationConnector.class.getName(), mModJGROUPS); mModJGROUPS = null; } if (mJSLPlocator != null) { AndroidContainer.THE_CONTAINER.unshareObject(Locator.class.getName(), mJSLPlocator); mJSLPlocator = null; } if (mJSLPadvertiser != null) { AndroidContainer.THE_CONTAINER.unshareObject(Advertiser.class.getName(), mJSLPadvertiser); mJSLPadvertiser = null; SLPCore.destroyMulticastSocket();// TODO place this better? SLPCore.stop(); } addPercent(5); // Then depending on what we are asked to do start the real or the fake connectors if (connect) { // Start the real connectors Log.v(TAG, "Starting network discovery and peering"); try { // First acquire multicast lock mLock.acquire(); // Then start JSLP library SLPCore.init(); SLPCore.initMulticastSocket(); mJSLPadvertiser = new AdvertiserImpl(); mJSLPlocator = new LocatorImpl(); AndroidContainer.THE_CONTAINER.shareObject(AndroidContext.THE_CONTEXT, mJSLPadvertiser, new Object[] { Advertiser.class.getName() }); AndroidContainer.THE_CONTAINER.shareObject(AndroidContext.THE_CONTEXT, mJSLPlocator, new Object[] { Locator.class.getName() }); Log.d(TAG, "Started libraries..."); // _____________________JGROUPS______________________ mModJGROUPS = new JGroupsCommunicationConnector(AndroidContext.THE_CONTEXT); Dictionary jGroupDCOnnector = Config.getProperties("mw.connectors.communication.jgroups.core"); if (jGroupDCOnnector != null) { mModJGROUPS.loadConfigurations(jGroupDCOnnector); } AndroidContainer.THE_CONTAINER.shareObject(AndroidContext.THE_CONTEXT, mModJGROUPS, new Object[] { CommunicationConnector.class.getName() }); Log.d(TAG, "Started the JGroupCommunicationConnector..."); // _____________________JSLP_________________________ mModJSLP = new SLPDiscoveryConnector(AndroidContext.THE_CONTEXT); Dictionary slpDConnectorProperties = Config.getProperties("mw.connectors.discovery.slp.core"); if (slpDConnectorProperties != null) { mModJSLP.loadConfigurations(slpDConnectorProperties); mModJSLP.init(); } AndroidContainer.THE_CONTAINER.shareObject(AndroidContext.THE_CONTEXT, mModJSLP, new Object[] { DiscoveryConnector.class.getName() }); Log.d(TAG, "Starting the SLPDiscoveryConnector..."); } catch (Exception e) { Log.e(TAG, "Error while initializing connector", e); } } else { // Start the fake connectors Log.v(TAG, "Starting stub discovery and peering"); mLock.release(); // Release multicast // _____________________JGROUPS_________________________ mModJGROUPS = new CommunicationConnectorWrapper(); AndroidContainer.THE_CONTAINER.shareObject(AndroidContext.THE_CONTEXT, mModJGROUPS, new Object[] { CommunicationConnector.class.getName() }); Log.d(TAG, "Starting the FAKE JGroupCommunicationConnector..."); // _____________________JSLP_________________________ mModJSLP = new DiscoveryConnectorWrapper(); AndroidContainer.THE_CONTAINER.shareObject(AndroidContext.THE_CONTEXT, mModJSLP, new Object[] { DiscoveryConnector.class.getName() }); Log.d(TAG, "Starting the FAKE SLPDiscoveryConnector..."); } // Restart AALSpaceManager to trigger AALSpace creation, only if it was already started! if (aalspaceflag) { // _________________AALSPACE MANAGER_____________________ AndroidContext tempCtxt = new AndroidContext("mw.managers.aalspace.osgi"); mModSPACEMANAGER = new AALSpaceManagerImpl(tempCtxt, Environment.getExternalStorageDirectory().getPath() + Config.getConfigDir() + "/mw.managers.aalspace.osgi"); Dictionary aalSpaceManagerProps = Config.getProperties("mw.managers.aalspace.core"); if (aalSpaceManagerProps == null) { aalSpaceManagerProps = new Hashtable<String, String>(); } else { mModSPACEMANAGER.loadConfigurations(aalSpaceManagerProps); } mModSPACEMANAGER.init(); AndroidContainer.THE_CONTAINER.shareObject(tempCtxt, mModSPACEMANAGER, new String[] { AALSpaceManager.class.getName(), AALSpaceEventHandler.class.getName() }); Log.d(TAG, "Started AALSPACE MANAGER again"); //TODO What to do with AbstractBus, which uses aalspacemanager too??? } addPercent(5); } /** * Stops the communication connectors, either real or fake. */ private synchronized void stopConnector() { // _____________________JSLP_________________________ if (mModJSLP != null) { try { mModJSLP.dispose();// -> Exception if wifi off, but must be done } catch (Exception e) { Log.e(TAG, "Could not dispose correctly the JSLP"); } AndroidContainer.THE_CONTAINER.unshareObject(DiscoveryConnector.class.getName(), mModJSLP); mModJSLP = null; } // _____________________JGROUPS_______________________ if (mModJGROUPS != null) { try { mModJGROUPS.dispose();// -> Exception if wifi off, but must be done } catch (Exception e) { Log.e(TAG, "Could not dispose correctly the JGROUPS"); } AndroidContainer.THE_CONTAINER.unshareObject(CommunicationConnector.class.getName(), mModJGROUPS); mModJGROUPS = null; } // Stop JSLP library if (mJSLPlocator != null) { AndroidContainer.THE_CONTAINER.unshareObject(Locator.class.getName(), mJSLPlocator); mJSLPlocator = null; } if (mJSLPadvertiser != null) { AndroidContainer.THE_CONTAINER.unshareObject(Advertiser.class.getName(), mJSLPadvertiser); mJSLPadvertiser = null; SLPCore.destroyMulticastSocket();//TODO place this better? SLPCore.stop(); } mLock.release(); // Release multicast lock } /** * Starts the middleware modules in the right order with the appropriate * sequence for each. Does not include the connectors. */ private synchronized void startMiddleware() { try { // _________________COMMUNICATION MODULE_________________ AndroidContext c1 = new AndroidContext("mw.modules.communication.osgi"); mModCOMMUNICATION = new CommunicationModuleImpl(c1); mModCOMMUNICATION.init(); AndroidContainer.THE_CONTAINER.shareObject(c1, mModCOMMUNICATION, new Object[] { CommunicationModule.class.getName() }); Log.d(TAG, "Started COMMUNICATION MODULE"); addPercent(5); // _________________AALSPACE MODULE_____________________ AndroidContext c2 = new AndroidContext("mw.modules.aalspace.osgi"); mModSPACEMODULE = new AALSpaceModuleImpl(c2); Dictionary aalSpaceModuleProp = Config.getProperties("mw.modules.aalspace.core"); if (aalSpaceModuleProp != null) { mModSPACEMODULE.loadConfigurations(aalSpaceModuleProp); } else { mModSPACEMODULE.loadConfigurations(new Hashtable<String, String>()); } mModSPACEMODULE.init(); AndroidContainer.THE_CONTAINER.shareObject(c2, mModSPACEMODULE, new Object[] { AALSpaceModule.class.getName() }); Log.d(TAG, "Started AALSPACE MODULE"); addPercent(5); // _________________CONTROL BROKER_____________________ AndroidContext c3 = new AndroidContext("mw.brokers.control.osgi"); mModCONTROLBROKER = new ControlBroker(c3); AndroidContainer.THE_CONTAINER.shareObject(c3, mModCONTROLBROKER, new Object[] { ControlBroker.class.getName() }); Log.d(TAG, "Started CONTROL BROKER"); addPercent(5); // _________________AALSPACE MANAGER_____________________ AndroidContext c4 = new AndroidContext("mw.managers.aalspace.osgi"); mModSPACEMANAGER = new AALSpaceManagerImpl(c4, Environment.getExternalStorageDirectory().getPath() + Config.getConfigDir() + "mw.managers.aalspace.osgi"); Dictionary aalSpaceManagerProps = Config.getProperties("mw.managers.aalspace.core"); if (aalSpaceManagerProps == null) { aalSpaceManagerProps = new Hashtable<String, String>(); } else { mModSPACEMANAGER.loadConfigurations(aalSpaceManagerProps); } mModSPACEMANAGER.init(); AndroidContainer.THE_CONTAINER.shareObject(c4, mModSPACEMANAGER, new String[] { AALSpaceManager.class.getName(), AALSpaceEventHandler.class.getName() }); mModSPACEMANAGER.addAALSpaceListener(this);// For listening to AAL space changes Log.d(TAG, "Started AALSPACE MANAGER"); addPercent(5); // _________________DEPLOY MANAGER_______________________ // TODO DEPLOY MANAGER // _________________DATA REPRESENTATION________________ SharedResources.moduleContext = AndroidContext.THE_CONTEXT; SharedResources.loadReasoningEngine(); SharedResources.setDefaults(); Log.d(TAG, "Started DATA REP"); addPercent(5); // _________________DATA SERIALIZATION_________________ TurtleUtil.moduleContext = AndroidContext.THE_CONTEXT; mModSERIALIZER = new TurtleSerializer(); AndroidContainer.THE_CONTAINER.shareObject(TurtleUtil.moduleContext, mModSERIALIZER, new Object[] { MessageContentSerializer.class.getName() }); AndroidContainer.THE_CONTAINER.shareObject(TurtleUtil.moduleContext, mModSERIALIZER, new Object[] { MessageContentSerializerEx.class.getName() }); Log.d(TAG, "Started DATA SER"); addPercent(5); // _________________BUS MODEL_________________________ AndroidContext c5 = new AndroidContext("mw.bus.model.osgi"); AbstractBus.initBrokerage(c5, mModSPACEMANAGER, mModCOMMUNICATION); BusMessage.setThisPeer(mModSPACEMANAGER.getMyPeerCard()); BusMessage.setMessageContentSerializer((MessageContentSerializer) mModSERIALIZER); Log.d(TAG, "Started BUS MODEL"); addPercent(5); // _________________SERVICE BUS_________________________ AndroidContext c6 = new AndroidContext("mw.bus.service.osgi"); Object[] busFetchParams = new Object[] { ServiceBusImpl.class.getName() }; Object[] busInjectFetchParams = new Object[] { CallInjector.class.getName() }; ServiceBusImpl.startModule(c6, busFetchParams, busFetchParams, busInjectFetchParams, busInjectFetchParams); Log.d(TAG, "Started SERVICE BUS"); addPercent(5); // _________________CONTEXT BUS_________________________ AndroidContext c7 = new AndroidContext("mw.bus.context.osgi"); busFetchParams = new Object[] { ContextBus.class.getName() }; ContextBusImpl.startModule(AndroidContainer.THE_CONTAINER, c7, busFetchParams, busFetchParams); Log.d(TAG, "Started CONTEXT BUS"); addPercent(5); if (Config.isUIHandler()) { //No need for UI bus if no Handler // _________________UI BUS_________________________ AndroidContext c8 = new AndroidContext("mw.bus.ui.osgi"); busFetchParams = new Object[] { IUIBus.class.getName() }; UIBusImpl.startModule(AndroidContainer.THE_CONTAINER, c8, busFetchParams, busFetchParams); Log.d(TAG, "Started UI BUS"); } addPercent(5); } catch (Exception e) { Log.e(TAG, "Error while initializing MW", e); } } /** * Stops the middleware modules in order, with the appropriate sequence for * each. Does not include the connectors. */ private synchronized void stopMiddleware() { // _________________UI BUS_________________________ UIBusImpl.stopModule(); //will it work if not started? Looks like it does // _________________CONTEXT BUS_________________________ ContextBusImpl.stopModule(); // _________________SERVICE BUS_________________________ ServiceBusImpl.stopModule(); // _________________BUS MODEL_________________________ //BusModel -> Nothing // _________________/DATA SERIALIZATION_________________ //DataSerialization -> Nothing TODO check if dont need to unshare if (mModSERIALIZER != null) { AndroidContainer.THE_CONTAINER.unshareObject(MessageContentSerializerEx.class.getName(), mModSERIALIZER); AndroidContainer.THE_CONTAINER.unshareObject(MessageContentSerializer.class.getName(), mModSERIALIZER); mModSERIALIZER = null; } // _________________DATA REPRESENTATION________________ SharedResources.unloadReasoningEngine(); // _________________DEPLOY MANAGER_____________________ // TODO DEPLOY MANAGER // _________________AALSPACE MANAGER_____________________ if (mModSPACEMANAGER != null) { mModSPACEMANAGER.removeAALSpaceListener(this); mModSPACEMANAGER.dispose(); AndroidContainer.THE_CONTAINER.removeSharedObjectListener(mModSPACEMANAGER); AndroidContainer.THE_CONTAINER.unshareObject(AALSpaceManager.class.getName(), mModSPACEMANAGER); mModSPACEMANAGER = null; } // _________________CONTROL BROKER_____________________ if (mModCONTROLBROKER != null) { mModCONTROLBROKER.dispose(); AndroidContainer.THE_CONTAINER.removeSharedObjectListener(mModCONTROLBROKER); AndroidContainer.THE_CONTAINER.unshareObject(AALSpaceManager.class.getName(), mModCONTROLBROKER); mModCONTROLBROKER = null; } // _________________AALSPACE MODULE_____________________ if (mModSPACEMODULE != null) { mModSPACEMODULE.dispose(); AndroidContainer.THE_CONTAINER.removeSharedObjectListener(mModSPACEMODULE); AndroidContainer.THE_CONTAINER.unshareObject(AALSpaceManager.class.getName(), mModSPACEMODULE); mModSPACEMODULE = null; } // _________________COMMUNICATION MODULE_________________ if (mModCOMMUNICATION != null) { mModCOMMUNICATION.dispose(); AndroidContainer.THE_CONTAINER.unshareObject(CommunicationModule.class.getName(), mModCOMMUNICATION); } } /** * Start the modules needed for the UI Handler to start. */ private synchronized void startHandler() { new Thread(new Runnable() { public void run() { // _________________UI HANDLER_________________________ mModHANDLER = new AndroidHandler(AndroidContext.THE_CONTEXT, Constants.uAAL_MIDDLEWARE_LOCAL_ID_PREFIX + Config.getUAALUser()); AndroidContainer.THE_CONTAINER.shareObject(AndroidContext.THE_CONTEXT, mModHANDLER, new String[] { AndroidHandler.class.getName(), AndroidHandler.class.getName() }); mModHANDLER.render(); Log.d(TAG, "Started UI HANDLER"); } }, TAG_THREAD_UI).start();// Do in thread because if there is no coord it would block addPercent(5); } /** * Stops the modules needed for the UI Handler to stop. */ private synchronized void stopHandler() { // _________________UI HANDLER_________________________ if (mModHANDLER != null) { mModHANDLER.close();// TODO Close better? AndroidContainer.THE_CONTAINER.unshareObject(AndroidHandler.class.getName(), mModHANDLER); mModHANDLER = null; } } /** * Start the modules needed for the RI AAL Space Gateway/R API to start. */ private synchronized void startGateway() { switch (Config.getRemoteType()) { case AppConstants.REMOTE_TYPE_GW: // _________________BUS TRACKER_________________ org.universAAL.middleware.tracker.impl.Activator.fetchParams = new Object[] { IBusMemberRegistry.class.getName() }; mModTRACKER = new BusMemberRegistryImpl(AndroidContext.THE_CONTEXT); AndroidContainer.THE_CONTAINER.shareObject(AndroidContext.THE_CONTEXT, mModTRACKER, new Object[] { IBusMemberRegistry.class.getName() }); Log.d(TAG, "Started BUS TRACKER"); // _________________GATEWAY_________________________ ModuleContext c8 = new AndroidContext("ri.gateway.multitenant"); Dictionary gatewayProps = Config.getProperties("ri.gateway.communicator.core"); try { mModGATEWAY = new Gateway(); mModGATEWAY.start(c8); Log.d(TAG, "Started GATEWAY"); } catch (Exception e) { Log.e(TAG, "Error while initializing Gateway", e); } break; case AppConstants.REMOTE_TYPE_RAPI: // Check Play Services and register in GCM if not already if (RAPIManager.checkPlayServices(getApplicationContext())) { String mRegID = RAPIManager.getRegistrationId(getApplicationContext()); if (mRegID.isEmpty()) { RAPIManager.registerInThread(getApplicationContext()); } else {//Already registered in GCM, but maybe not in uAAL yet RAPIManager.invoke(RAPIManager.REGISTER, mRegID); } } else { //TODO show error // Toast.makeText(getApplicationContext(), R.string.warning_gplay, Toast.LENGTH_LONG).show(); } break; default: break; } AndroidRegistry.sync();//Makes all proxies register to remote node (if possible) } /** * Stops the modules needed for the RI AAL Space Gateway/R API to stop. */ private synchronized void stopGateway() { switch (Config.getRemoteType()) { case AppConstants.REMOTE_TYPE_GW: // _________________GATEWAY_________________________ if (mModGATEWAY != null) { try { mModGATEWAY.getInstance().stop(mModGATEWAY.getInstance().context); mModGATEWAY = null; } catch (Exception e) { Log.e(TAG, "Cannot stop the Gateway correctly"); } } // _________________BUS TRACKER_________________ if (mModTRACKER != null) { mModTRACKER.removeRegistryListeners(); AndroidContainer.THE_CONTAINER.unshareObject(IBusMemberRegistry.class.getName(), mModTRACKER); mModTRACKER = null; } Log.d(TAG, "Stopped GATEWAY"); break; case AppConstants.REMOTE_TYPE_RAPI: // Check Play Services and register in GCM if not already if (RAPIManager.checkPlayServices(getApplicationContext())) { String mRegID = RAPIManager.getRegistrationId(getApplicationContext()); if (mRegID.isEmpty()) { RAPIManager.registerInThread(getApplicationContext()); } else {//mRegID not really needed, but just in case in the future... RAPIManager.invokeInThread(RAPIManager.UNREGISTER, mRegID); } } else { //TODO show error better // Toast.makeText(getApplicationContext(), R.string.warning_gplay, Toast.LENGTH_LONG).show(); } break; default: break; } } /** * Determines if GW for remtoe node (GW or R API) is needed in current * situation. * * @return True if Remote mode ALWAYS, or remote mode WIFIOFF and the WIFI * is OFF or STRANGER */ public static boolean isGWrequired() { return (Config.getRemoteMode() == AppConstants.REMOTE_MODE_ALWAYS || (Config.getRemoteMode() == AppConstants.REMOTE_MODE_WIFIOFF && (mCurrentWIFI == AppConstants.WIFI_OFF || mCurrentWIFI == AppConstants.WIFI_STRANGER))); } /** * Helper method to determine if there is a WiFi data connection. * * @return True if there is one. */ // private boolean isWifiOn(){ // try { // Thread.sleep(3000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // ConnectivityManager connectivityManager = (ConnectivityManager) MiddlewareService.this // .getSystemService(Context.CONNECTIVITY_SERVICE); // NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo(); // return (netInfo != null && netInfo.getType() == ConnectivityManager.TYPE_WIFI); // } @SuppressLint("NewApi") private void requestLollipopWifi() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ConnectivityManager connectivityManager = (ConnectivityManager) MiddlewareService.this .getSystemService(Context.CONNECTIVITY_SERVICE); connectivityManager.requestNetwork( new NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build(), new ConnectivityManager.NetworkCallback() { public void onAvailable(Network network) { Log.d(TAG, "Setting process default network " + network.toString()); ConnectivityManager.setProcessDefaultNetwork(network); } }); } } //All this "isOurWifi" thing is for knowing when to start the GW or connector. /** * Sets the current active WiFi connection as the network where "our" AAL * Space is located. */ private void thisIsOurWifi() { // if (isWifiOn()) { WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); String networkId = wifiInfo.getSSID(); PreferenceManager.getDefaultSharedPreferences(this).edit().putString(AppConstants.MY_WIFI, networkId) .commit(); Log.i(TAG, "Setting home space Wifi: " + networkId); // } } /** * Check what is the current connection status of WiFi. * * @return Constant representing the status. */ private int checkWifi() { // if (isWifiOn()) { WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); if (wifiInfo.getNetworkId() == -1) { //No network actually Log.i(TAG, "WIFI CHECK: Wifi is not on"); return AppConstants.WIFI_OFF; } String networkId = wifiInfo.getSSID(); String home = PreferenceManager.getDefaultSharedPreferences(this).getString(AppConstants.MY_WIFI, AppConstants.NO_WIFI); Log.i(TAG, "WIFI CHECK: Evaluating: " + networkId); if (home.equals(AppConstants.NO_WIFI)) { Log.i(TAG, "WIFI CHECK: We still do not have a home wifi, maybe this one will be?"); return AppConstants.WIFI_NOTSET; } else if (networkId.equals(home)) { Log.i(TAG, "WIFI CHECK: We have a home wifi, and we are in it!"); return AppConstants.WIFI_HOME; } else { Log.i(TAG, "WIFI CHECK: We have a home wifi, but it is not this one. If you want it to be, clear app data"); return AppConstants.WIFI_STRANGER; } // } // Log.i(TAG, "WIFI CHECK: Wifi is not on"); // return AppConstants.WIFI_OFF; } private void addPercent(int percent) { if (mPercentage < 100) { mPercentage += percent; } notifyPercent(); } private void notifyPercent() { // TODO use pending intent? isnt a single sticky intent always there with this already? Intent intent = new Intent(AppConstants.ACTION_UI_PROGRESS); intent.setFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING + Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.setPackage(getPackageName()); sendBroadcast(intent); } public void aalSpaceJoined(AALSpaceDescriptor spaceDescriptor) { String home = PreferenceManager.getDefaultSharedPreferences(this).getString(AppConstants.MY_WIFI, AppConstants.NO_WIFI); if (home.equals(AppConstants.NO_WIFI)) { // This is the first time we connect to a space thisIsOurWifi(); } if (Config.getRemoteMode() == AppConstants.REMOTE_MODE_WIFIOFF) { stopGateway();//stop the GW because we are in a space (probably already stopped) } } public void newPeerJoined(PeerCard peer) { String home = PreferenceManager.getDefaultSharedPreferences(this).getString(AppConstants.MY_WIFI, AppConstants.NO_WIFI); if (home.equals(AppConstants.NO_WIFI)) { // This is the first time we connect to a space thisIsOurWifi(); } if (Config.getRemoteMode() == AppConstants.REMOTE_MODE_WIFIOFF) { stopGateway();//stop the GW because we are in a space (probably already stopped) } } public void aalSpaceLost(AALSpaceDescriptor spaceDescriptor) { // TODO Auto-generated method stub } public void peerLost(PeerCard peer) { // TODO Auto-generated method stub } public void aalSpaceStatusChanged(AALSpaceStatus status) { // TODO Auto-generated method stub } }