diff options
author | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2017-03-11 22:15:03 +0100 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2017-03-11 22:15:03 +0100 |
commit | 85901329b0794b136b96bf745f4ab1572806fc89 (patch) | |
tree | f23da7e97cae727f39d825f0fef8348cffb238e4 /src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java | |
parent | 3db2e44f186c59429901b2c899e139ea60117a55 (diff) | |
parent | cf5da997da8820b4050f5b87ee9440a0ede36d1f (diff) | |
download | jitsi-85901329b0794b136b96bf745f4ab1572806fc89.zip jitsi-85901329b0794b136b96bf745f4ab1572806fc89.tar.gz jitsi-85901329b0794b136b96bf745f4ab1572806fc89.tar.bz2 |
Signed-off-by: Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de>
Diffstat (limited to 'src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java')
-rw-r--r-- | src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java | 1274 |
1 files changed, 637 insertions, 637 deletions
diff --git a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java index c25504f..c58805b 100644 --- a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java +++ b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java @@ -1,4 +1,4 @@ -/*
+/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,639 +15,639 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.sysactivity;
-
-import java.util.*;
-
-import net.java.sip.communicator.service.sysactivity.*;
-import net.java.sip.communicator.service.sysactivity.event.*;
-import net.java.sip.communicator.util.Logger;
-
-import org.jitsi.util.*;
-
-/**
- * Service implementation listens for computer changes as sleeping, network
- * change, inactivity.
- *
- * @author Damian Minkov
- */
-public class SystemActivityNotificationsServiceImpl
- implements SystemActivityNotifications.NotificationsDelegate,
- SystemActivityNotificationsService,
- Runnable
-{
- /**
- * The <tt>Logger</tt> used by this
- * <tt>SystemActivityNotificationsServiceImpl</tt> for logging output.
- */
- private final Logger logger
- = Logger.getLogger(SystemActivityNotificationsServiceImpl.class);
-
- /**
- * The thread dispatcher of network change events.
- */
- private final SystemActivityEventDispatcher eventDispatcher
- = new SystemActivityEventDispatcher();
-
- /**
- * A list of listeners registered for idle events.
- */
- private final Map<SystemActivityChangeListener,Long> idleChangeListeners
- = new HashMap<SystemActivityChangeListener, Long>();
-
- /**
- * Listeners which are fired for idle state and which will be fired
- * with idle end when needed.
- */
- private final List<SystemActivityChangeListener> listenersInIdleState
- = new ArrayList<SystemActivityChangeListener>();
-
- /**
- * The interval between checks when not idle.
- */
- private static final int CHECK_FOR_IDLE_DEFAULT = 30 * 1000;
-
- /**
- * The interval between checks when idle. The interval is shorter
- * so we can react almost immediately when we are active again.
- */
- private static final int CHECK_FOR_IDLE_WHEN_IDLE = 1000;
-
- /**
- * The time in milliseconds between two checks for system idle.
- */
- private static int idleStateCheckDelay = CHECK_FOR_IDLE_DEFAULT;
-
- /**
- * Whether current service is started or stopped.
- */
- private boolean running = false;
-
- /**
- * The time when we received latest network change event.
- */
- private long lastNetworkChange = -1;
-
- /**
- * Sometimes (on windows) we got several network change events
- * this is the time after which latest event we will skip next events.
- */
- private static final long NETWORK_EVENT_SILENT_TIME = 10*1000;
-
- /**
- * Whether network is currently connected.
- */
- private Boolean networkIsConnected = null;
-
- /**
- * The linux impl class name.
- */
- private static final String SYSTEM_ACTIVITY_MANAGER_LINUX_CLASS
- = "net.java.sip.communicator.impl.sysactivity.NetworkManagerListenerImpl";
-
- /**
- * The android impl class name.
- */
- private static final String SYSTEM_ACTIVITY_MANAGER_ANDROID_CLASS
- = "net.java.sip.communicator.impl.sysactivity.ConnectivityManagerListenerImpl";
-
- /**
- * The currently instantiated and working manager.
- */
- private SystemActivityManager currentRunningManager = null;
-
- /**
- * Init and start notifications.
- */
- public void start()
- {
- running = true;
-
- // set the delegate and start notification in new thread
- // make sure we don't block startup process
- Thread notifystartThread
- = new Thread(
- new Runnable()
- {
- public void run()
- {
- SystemActivityNotifications.setDelegate(
- SystemActivityNotificationsServiceImpl.this);
- SystemActivityNotifications.start();
- }
- },
- "SystemActivityNotificationsServiceImpl");
- notifystartThread.setDaemon(true);
- notifystartThread.start();
-
- if(isSupported(SystemActivityEvent.EVENT_SYSTEM_IDLE))
- {
- // a thread periodically checks system idle state and if it pass the
- // idle time for a particular listener, will inform it.
- Thread idleNotifyThread = new Thread(
- this,
- "SystemActivityNotificationsServiceImpl.IdleNotifyThread");
- idleNotifyThread.setDaemon(true);
- idleNotifyThread.start();
- }
-
- if (getCurrentRunningManager() != null)
- getCurrentRunningManager().start();
- }
-
- /**
- * Stop notifications.
- */
- public void stop()
- {
- SystemActivityNotifications.stop();
-
- if (getCurrentRunningManager() != null)
- getCurrentRunningManager().stop();
-
- eventDispatcher.stop();
-
- running = false;
-
- synchronized(this)
- {
- this.notifyAll();
- }
- }
-
- /**
- * Registers a listener that would be notified of changes that have occurred
- * in the underlying system.
- *
- * @param listener the listener that we'd like to register for changes in
- * the underlying system.
- */
- public void addSystemActivityChangeListener(
- SystemActivityChangeListener listener)
- {
- eventDispatcher.addSystemActivityChangeListener(listener);
- }
-
- /**
- * Remove the specified listener so that it won't receive further
- * notifications of changes that occur in the underlying system
- *
- * @param listener the listener to remove.
- */
- public void removeSystemActivityChangeListener(
- SystemActivityChangeListener listener)
- {
- eventDispatcher.removeSystemActivityChangeListener(listener);
- }
-
- /**
- * Registers a listener that would be notified for idle of the system
- * for <tt>idleTime</tt>.
- *
- * @param idleTime the time in milliseconds after which we will consider
- * system to be idle. This doesn't count when system seems idle as
- * monitor is off or screensaver is on, or desktop is locked.
- * @param listener the listener that we'd like to register for changes in
- * the underlying system.
- */
- public void addIdleSystemChangeListener(
- long idleTime,
- SystemActivityChangeListener listener)
- {
- synchronized (idleChangeListeners)
- {
- if (idleTime > 0
- && !idleChangeListeners.containsKey(listener))
- idleChangeListeners.put(listener, idleTime);
- }
- }
-
- /**
- * Remove the specified listener so that it won't receive further
- * notifications for idle system.
- *
- * @param listener the listener to remove.
- */
- public void removeIdleSystemChangeListener(
- SystemActivityChangeListener listener)
- {
- synchronized (idleChangeListeners)
- {
- idleChangeListeners.remove(listener);
- }
- }
-
- /**
- * The time since last user input. The time the system has been idle.
- * @return time the system has been idle.
- */
- public long getTimeSinceLastInput()
- {
- if(SystemActivityNotifications.isLoaded())
- return SystemActivityNotifications.getLastInput();
- else
- return -1;
- }
-
- /**
- * Callback method when receiving notifications.
- *
- * @param type type of the notification.
- */
- public void notify(int type)
- {
- SystemActivityEvent evt = null;
- switch(type)
- {
- case SystemActivityNotifications.NOTIFY_SLEEP :
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_SLEEP);
- break;
- case SystemActivityNotifications.NOTIFY_WAKE :
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_WAKE);
- break;
- case SystemActivityNotifications.NOTIFY_DISPLAY_SLEEP :
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_DISPLAY_SLEEP);
- break;
- case SystemActivityNotifications.NOTIFY_DISPLAY_WAKE :
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_DISPLAY_WAKE);
- break;
- case SystemActivityNotifications.NOTIFY_SCREENSAVER_START :
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_SCREENSAVER_START);
- break;
- case SystemActivityNotifications.NOTIFY_SCREENSAVER_WILL_STOP :
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_SCREENSAVER_WILL_STOP);
- break;
- case SystemActivityNotifications.NOTIFY_SCREENSAVER_STOP :
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_SCREENSAVER_STOP);
- break;
- case SystemActivityNotifications.NOTIFY_SCREEN_LOCKED :
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_SCREEN_LOCKED);
- break;
- case SystemActivityNotifications.NOTIFY_SCREEN_UNLOCKED :
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_SCREEN_UNLOCKED);
- break;
- case SystemActivityNotifications.NOTIFY_NETWORK_CHANGE :
- {
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_NETWORK_CHANGE);
- break;
- }
- case SystemActivityNotifications.NOTIFY_DNS_CHANGE :
- {
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_DNS_CHANGE);
- break;
- }
- case SystemActivityNotifications.NOTIFY_QUERY_ENDSESSION :
- {
- // both events QUERY_ENDSESSION and ENDSESSION
- // depend on the result one after another
- // we don't put them in new thread in order to give control
- // in the bundles using this events.
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_QUERY_ENDSESSION);
- eventDispatcher.fireSystemActivityEventCurrentThread(evt);
-
- return;
- }
- case SystemActivityNotifications.NOTIFY_ENDSESSION :
- {
- // both events QUERY_ENDSESSION and ENDSESSION
- // depend on the result one after another
- // we don't put them in new thread in order to give control
- // in the bundles using this events.
- evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_ENDSESSION);
- eventDispatcher.fireSystemActivityEventCurrentThread(evt);
-
- return;
- }
- }
-
- if (evt != null)
- fireSystemActivityEvent(evt);
- }
-
- /**
- * Callback method when receiving special network notifications.
- *
- * @param family family of network change (ipv6, ipv4)
- * AF_UNSPEC = 0 (The address family is unspecified.)
- * AF_INET = 2 (The Internet Protocol version 4 (IPv4) address family)
- * AF_INET6 = 23 (The Internet Protocol version 6 (IPv6) address family)
- * @param luidIndex unique index of interface
- * @param name name of the interface
- * @param type of the interface
- * Possible values for the interface type are listed in the Ipifcons.h file.
- * common values:
- * IF_TYPE_OTHER = 1 (Some other type of network interface.)
- * IF_TYPE_ETHERNET_CSMACD = 6 (An Ethernet network interface.)
- * IF_TYPE_ISO88025_TOKENRING = 9 (A token ring network interface.)
- * IF_TYPE_PPP = 23 (A PPP network interface.)
- * IF_TYPE_SOFTWARE_LOOPBACK = 24 (A software loopback network interface.)
- * IF_TYPE_IEEE80211 = 71 (An IEEE 802.11 wireless network interface.)
- * IF_TYPE_TUNNEL = 131 (A tunnel type encapsulation network interface.)
- * IF_TYPE_IEEE1394 = 144 (An IEEE 1394 (Firewire) high performance
- * serial bus network interface.)
- * @param connected whether interface is connected or not.
- */
- public void notifyNetworkChange(
- int family,
- long luidIndex,
- String name,
- long type,
- boolean connected)
- {
- long current = System.currentTimeMillis();
- if(current - lastNetworkChange <= NETWORK_EVENT_SILENT_TIME
- && (networkIsConnected != null && networkIsConnected.equals(connected)))
- {
- networkIsConnected = connected;
- return;
- }
-
- lastNetworkChange = current;
- networkIsConnected = connected;
-
- SystemActivityEvent evt = new SystemActivityEvent(this,
- SystemActivityEvent.EVENT_NETWORK_CHANGE);
- fireSystemActivityEvent(evt);
- }
-
- /**
- * The thread run method that handles idle notifies.
- *
- * @see Thread#run()
- */
- public void run()
- {
- while(running)
- {
- try
- {
- long idleTime = 0;
- if(idleChangeListeners.size() > 0)
- {
- // check
- idleTime = SystemActivityNotifications.getLastInput();
-
- if((idleTime < idleStateCheckDelay)
- && (listenersInIdleState.size() > 0))
- {
- for(SystemActivityChangeListener l
- : listenersInIdleState)
- {
- fireSystemIdleEndEvent(l);
- }
- listenersInIdleState.clear();
- }
-
- for(Map.Entry<SystemActivityChangeListener, Long> entry
- : idleChangeListeners.entrySet())
- {
- SystemActivityChangeListener listener =
- entry.getKey();
-
- if(!listenersInIdleState.contains(listener)
- && (entry.getValue() <= idleTime))
- {
- fireSystemIdleEvent(listener);
-
- listenersInIdleState.add(listener);
- }
- }
- }
-
- // if the minimum check for idle is X minutes
- // we will wait before checking (X - Y + 1sec)
- // where Y is the last idle time returned by OS
- if(listenersInIdleState.size() > 0)
- {
- idleStateCheckDelay = CHECK_FOR_IDLE_WHEN_IDLE;
- }
- else if(idleTime != 0)
- {
- long minIdleSetting = CHECK_FOR_IDLE_DEFAULT;
-
- if(!idleChangeListeners.isEmpty())
- minIdleSetting =
- Collections.min(idleChangeListeners.values());
-
- int newSetting = (int)(minIdleSetting - idleTime) + 1000;
-
- if(newSetting > 0)
- idleStateCheckDelay = newSetting;
- else
- idleStateCheckDelay = CHECK_FOR_IDLE_DEFAULT;
- }
- else
- {
- idleStateCheckDelay = CHECK_FOR_IDLE_DEFAULT;
- }
-
- // wait for the specified time
- synchronized(this)
- {
- this.wait(idleStateCheckDelay);
- }
- }
- catch(UnsatisfiedLinkError t)
- {
- logger.error("Missing native impl", t);
- return;
- }
- catch(Throwable t)
- {
- logger.error("Error checking for idle", t);
- }
- }
- }
-
- /**
- * Delivers the specified event to all registered listeners.
- *
- * @param evt the <tt>SystemActivityEvent</tt> that we'd like delivered to
- * all registered message listeners.
- */
- protected void fireSystemActivityEvent(SystemActivityEvent evt)
- {
- int eventID = evt.getEventID();
-
- // Add network activity info to track wake up problems.
- if (logger.isInfoEnabled()
- && ((eventID == SystemActivityEvent.EVENT_NETWORK_CHANGE)
- || (eventID == SystemActivityEvent.EVENT_DNS_CHANGE)))
- {
- logger.info("Received system activity event: " + evt);
- }
-
- if (eventID == SystemActivityEvent.EVENT_NETWORK_CHANGE)
- {
- // Give time to Java to dispatch same event and populate its network
- // interfaces.
- eventDispatcher.fireSystemActivityEvent(evt, 500);
- }
- else
- eventDispatcher.fireSystemActivityEvent(evt);
- }
-
- /**
- * Delivers the specified event to all registered listeners.
- *
- * @param listener listener to inform
- */
- protected void fireSystemIdleEvent(SystemActivityChangeListener listener)
- {
- SystemActivityEvent evt
- = new SystemActivityEvent(
- this,
- SystemActivityEvent.EVENT_SYSTEM_IDLE);
-
- if (logger.isDebugEnabled())
- logger.debug("Dispatching SystemActivityEvent evt=" + evt);
-
- try
- {
- listener.activityChanged(evt);
- }
- catch (Throwable t)
- {
- if (t instanceof ThreadDeath)
- throw (ThreadDeath) t;
- else
- logger.error("Error delivering event", t);
- }
- }
-
- /**
- * Delivers the specified event to listener.
- *
- * @param listener listener to inform
- */
- protected void fireSystemIdleEndEvent(
- SystemActivityChangeListener listener)
- {
- SystemActivityEvent evt
- = new SystemActivityEvent(
- this,
- SystemActivityEvent.EVENT_SYSTEM_IDLE_END);
-
- if (logger.isDebugEnabled())
- logger.debug("Dispatching SystemActivityEvent evt=" + evt);
-
- try
- {
- listener.activityChanged(evt);
- }
- catch (Throwable t)
- {
- if (t instanceof ThreadDeath)
- throw (ThreadDeath) t;
- else
- logger.error("Error delivering event", t);
- }
- }
-
- /**
- * Can check whether an event id is supported on
- * current operation system.
- * Simple return what is implemented in native, and checks
- * are made when possible, for example linux cannot connect
- * to NM through dbus.
- * @param eventID the event to check.
- * @return whether the supplied event id is supported.
- */
- public boolean isSupported(int eventID)
- {
- if(OSUtils.IS_WINDOWS)
- {
- switch(eventID)
- {
- case SystemActivityEvent.EVENT_SLEEP:
- case SystemActivityEvent.EVENT_WAKE:
- case SystemActivityEvent.EVENT_NETWORK_CHANGE:
- case SystemActivityEvent.EVENT_SYSTEM_IDLE:
- case SystemActivityEvent.EVENT_SYSTEM_IDLE_END:
- return SystemActivityNotifications.isLoaded();
- default:
- return false;
- }
- }
- else if(OSUtils.IS_MAC)
- {
- return SystemActivityNotifications.isLoaded();
- }
- else if(OSUtils.IS_LINUX)
- {
- switch(eventID)
- {
- case SystemActivityEvent.EVENT_SLEEP:
- case SystemActivityEvent.EVENT_NETWORK_CHANGE:
- {
- SystemActivityManager currentRunningManager
- = getCurrentRunningManager();
-
- return
- (currentRunningManager == null)
- ? false
- : currentRunningManager.isConnected();
- }
- case SystemActivityEvent.EVENT_SYSTEM_IDLE:
- case SystemActivityEvent.EVENT_SYSTEM_IDLE_END:
- return SystemActivityNotifications.isLoaded();
- default:
- return false;
- }
- }
- else if(OSUtils.IS_ANDROID)
- {
- return (eventID == SystemActivityEvent.EVENT_NETWORK_CHANGE);
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Returns or instantiate the manager.
- * @return
- */
- private SystemActivityManager getCurrentRunningManager()
- {
- if(currentRunningManager == null)
- {
- try
- {
- String className = null;
- if(OSUtils.IS_LINUX)
- {
- className = SYSTEM_ACTIVITY_MANAGER_LINUX_CLASS;
- }
- else if(OSUtils.IS_ANDROID)
- {
- className = SYSTEM_ACTIVITY_MANAGER_ANDROID_CLASS;
- }
-
- if(className != null)
- currentRunningManager = (SystemActivityManager)
- Class.forName(className).newInstance();
- }
- catch(Throwable t)
- {
- logger.error("Error creating manager", t);
- }
- }
-
- return currentRunningManager;
- }
-}
+package net.java.sip.communicator.impl.sysactivity; + +import java.util.*; + +import net.java.sip.communicator.service.sysactivity.*; +import net.java.sip.communicator.service.sysactivity.event.*; +import net.java.sip.communicator.util.Logger; + +import org.jitsi.util.*; + +/** + * Service implementation listens for computer changes as sleeping, network + * change, inactivity. + * + * @author Damian Minkov + */ +public class SystemActivityNotificationsServiceImpl + implements SystemActivityNotifications.NotificationsDelegate, + SystemActivityNotificationsService, + Runnable +{ + /** + * The <tt>Logger</tt> used by this + * <tt>SystemActivityNotificationsServiceImpl</tt> for logging output. + */ + private final Logger logger + = Logger.getLogger(SystemActivityNotificationsServiceImpl.class); + + /** + * The thread dispatcher of network change events. + */ + private final SystemActivityEventDispatcher eventDispatcher + = new SystemActivityEventDispatcher(); + + /** + * A list of listeners registered for idle events. + */ + private final Map<SystemActivityChangeListener,Long> idleChangeListeners + = new HashMap<SystemActivityChangeListener, Long>(); + + /** + * Listeners which are fired for idle state and which will be fired + * with idle end when needed. + */ + private final List<SystemActivityChangeListener> listenersInIdleState + = new ArrayList<SystemActivityChangeListener>(); + + /** + * The interval between checks when not idle. + */ + private static final int CHECK_FOR_IDLE_DEFAULT = 30 * 1000; + + /** + * The interval between checks when idle. The interval is shorter + * so we can react almost immediately when we are active again. + */ + private static final int CHECK_FOR_IDLE_WHEN_IDLE = 1000; + + /** + * The time in milliseconds between two checks for system idle. + */ + private static int idleStateCheckDelay = CHECK_FOR_IDLE_DEFAULT; + + /** + * Whether current service is started or stopped. + */ + private boolean running = false; + + /** + * The time when we received latest network change event. + */ + private long lastNetworkChange = -1; + + /** + * Sometimes (on windows) we got several network change events + * this is the time after which latest event we will skip next events. + */ + private static final long NETWORK_EVENT_SILENT_TIME = 10*1000; + + /** + * Whether network is currently connected. + */ + private Boolean networkIsConnected = null; + + /** + * The linux impl class name. + */ + private static final String SYSTEM_ACTIVITY_MANAGER_LINUX_CLASS + = "net.java.sip.communicator.impl.sysactivity.NetworkManagerListenerImpl"; + + /** + * The android impl class name. + */ + private static final String SYSTEM_ACTIVITY_MANAGER_ANDROID_CLASS + = "net.java.sip.communicator.impl.sysactivity.ConnectivityManagerListenerImpl"; + + /** + * The currently instantiated and working manager. + */ + private SystemActivityManager currentRunningManager = null; + + /** + * Init and start notifications. + */ + public void start() + { + running = true; + + // set the delegate and start notification in new thread + // make sure we don't block startup process + Thread notifystartThread + = new Thread( + new Runnable() + { + public void run() + { + SystemActivityNotifications.setDelegate( + SystemActivityNotificationsServiceImpl.this); + SystemActivityNotifications.start(); + } + }, + "SystemActivityNotificationsServiceImpl"); + notifystartThread.setDaemon(true); + notifystartThread.start(); + + if(isSupported(SystemActivityEvent.EVENT_SYSTEM_IDLE)) + { + // a thread periodically checks system idle state and if it pass the + // idle time for a particular listener, will inform it. + Thread idleNotifyThread = new Thread( + this, + "SystemActivityNotificationsServiceImpl.IdleNotifyThread"); + idleNotifyThread.setDaemon(true); + idleNotifyThread.start(); + } + + if (getCurrentRunningManager() != null) + getCurrentRunningManager().start(); + } + + /** + * Stop notifications. + */ + public void stop() + { + SystemActivityNotifications.stop(); + + if (getCurrentRunningManager() != null) + getCurrentRunningManager().stop(); + + eventDispatcher.stop(); + + running = false; + + synchronized(this) + { + this.notifyAll(); + } + } + + /** + * Registers a listener that would be notified of changes that have occurred + * in the underlying system. + * + * @param listener the listener that we'd like to register for changes in + * the underlying system. + */ + public void addSystemActivityChangeListener( + SystemActivityChangeListener listener) + { + eventDispatcher.addSystemActivityChangeListener(listener); + } + + /** + * Remove the specified listener so that it won't receive further + * notifications of changes that occur in the underlying system + * + * @param listener the listener to remove. + */ + public void removeSystemActivityChangeListener( + SystemActivityChangeListener listener) + { + eventDispatcher.removeSystemActivityChangeListener(listener); + } + + /** + * Registers a listener that would be notified for idle of the system + * for <tt>idleTime</tt>. + * + * @param idleTime the time in milliseconds after which we will consider + * system to be idle. This doesn't count when system seems idle as + * monitor is off or screensaver is on, or desktop is locked. + * @param listener the listener that we'd like to register for changes in + * the underlying system. + */ + public void addIdleSystemChangeListener( + long idleTime, + SystemActivityChangeListener listener) + { + synchronized (idleChangeListeners) + { + if (idleTime > 0 + && !idleChangeListeners.containsKey(listener)) + idleChangeListeners.put(listener, idleTime); + } + } + + /** + * Remove the specified listener so that it won't receive further + * notifications for idle system. + * + * @param listener the listener to remove. + */ + public void removeIdleSystemChangeListener( + SystemActivityChangeListener listener) + { + synchronized (idleChangeListeners) + { + idleChangeListeners.remove(listener); + } + } + + /** + * The time since last user input. The time the system has been idle. + * @return time the system has been idle. + */ + public long getTimeSinceLastInput() + { + if(SystemActivityNotifications.isLoaded()) + return SystemActivityNotifications.getLastInput(); + else + return -1; + } + + /** + * Callback method when receiving notifications. + * + * @param type type of the notification. + */ + public void notify(int type) + { + SystemActivityEvent evt = null; + switch(type) + { + case SystemActivityNotifications.NOTIFY_SLEEP : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_SLEEP); + break; + case SystemActivityNotifications.NOTIFY_WAKE : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_WAKE); + break; + case SystemActivityNotifications.NOTIFY_DISPLAY_SLEEP : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_DISPLAY_SLEEP); + break; + case SystemActivityNotifications.NOTIFY_DISPLAY_WAKE : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_DISPLAY_WAKE); + break; + case SystemActivityNotifications.NOTIFY_SCREENSAVER_START : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_SCREENSAVER_START); + break; + case SystemActivityNotifications.NOTIFY_SCREENSAVER_WILL_STOP : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_SCREENSAVER_WILL_STOP); + break; + case SystemActivityNotifications.NOTIFY_SCREENSAVER_STOP : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_SCREENSAVER_STOP); + break; + case SystemActivityNotifications.NOTIFY_SCREEN_LOCKED : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_SCREEN_LOCKED); + break; + case SystemActivityNotifications.NOTIFY_SCREEN_UNLOCKED : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_SCREEN_UNLOCKED); + break; + case SystemActivityNotifications.NOTIFY_NETWORK_CHANGE : + { + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_NETWORK_CHANGE); + break; + } + case SystemActivityNotifications.NOTIFY_DNS_CHANGE : + { + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_DNS_CHANGE); + break; + } + case SystemActivityNotifications.NOTIFY_QUERY_ENDSESSION : + { + // both events QUERY_ENDSESSION and ENDSESSION + // depend on the result one after another + // we don't put them in new thread in order to give control + // in the bundles using this events. + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_QUERY_ENDSESSION); + eventDispatcher.fireSystemActivityEventCurrentThread(evt); + + return; + } + case SystemActivityNotifications.NOTIFY_ENDSESSION : + { + // both events QUERY_ENDSESSION and ENDSESSION + // depend on the result one after another + // we don't put them in new thread in order to give control + // in the bundles using this events. + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_ENDSESSION); + eventDispatcher.fireSystemActivityEventCurrentThread(evt); + + return; + } + } + + if (evt != null) + fireSystemActivityEvent(evt); + } + + /** + * Callback method when receiving special network notifications. + * + * @param family family of network change (ipv6, ipv4) + * AF_UNSPEC = 0 (The address family is unspecified.) + * AF_INET = 2 (The Internet Protocol version 4 (IPv4) address family) + * AF_INET6 = 23 (The Internet Protocol version 6 (IPv6) address family) + * @param luidIndex unique index of interface + * @param name name of the interface + * @param type of the interface + * Possible values for the interface type are listed in the Ipifcons.h file. + * common values: + * IF_TYPE_OTHER = 1 (Some other type of network interface.) + * IF_TYPE_ETHERNET_CSMACD = 6 (An Ethernet network interface.) + * IF_TYPE_ISO88025_TOKENRING = 9 (A token ring network interface.) + * IF_TYPE_PPP = 23 (A PPP network interface.) + * IF_TYPE_SOFTWARE_LOOPBACK = 24 (A software loopback network interface.) + * IF_TYPE_IEEE80211 = 71 (An IEEE 802.11 wireless network interface.) + * IF_TYPE_TUNNEL = 131 (A tunnel type encapsulation network interface.) + * IF_TYPE_IEEE1394 = 144 (An IEEE 1394 (Firewire) high performance + * serial bus network interface.) + * @param connected whether interface is connected or not. + */ + public void notifyNetworkChange( + int family, + long luidIndex, + String name, + long type, + boolean connected) + { + long current = System.currentTimeMillis(); + if(current - lastNetworkChange <= NETWORK_EVENT_SILENT_TIME + && (networkIsConnected != null && networkIsConnected.equals(connected))) + { + networkIsConnected = connected; + return; + } + + lastNetworkChange = current; + networkIsConnected = connected; + + SystemActivityEvent evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_NETWORK_CHANGE); + fireSystemActivityEvent(evt); + } + + /** + * The thread run method that handles idle notifies. + * + * @see Thread#run() + */ + public void run() + { + while(running) + { + try + { + long idleTime = 0; + if(idleChangeListeners.size() > 0) + { + // check + idleTime = SystemActivityNotifications.getLastInput(); + + if((idleTime < idleStateCheckDelay) + && (listenersInIdleState.size() > 0)) + { + for(SystemActivityChangeListener l + : listenersInIdleState) + { + fireSystemIdleEndEvent(l); + } + listenersInIdleState.clear(); + } + + for(Map.Entry<SystemActivityChangeListener, Long> entry + : idleChangeListeners.entrySet()) + { + SystemActivityChangeListener listener = + entry.getKey(); + + if(!listenersInIdleState.contains(listener) + && (entry.getValue() <= idleTime)) + { + fireSystemIdleEvent(listener); + + listenersInIdleState.add(listener); + } + } + } + + // if the minimum check for idle is X minutes + // we will wait before checking (X - Y + 1sec) + // where Y is the last idle time returned by OS + if(listenersInIdleState.size() > 0) + { + idleStateCheckDelay = CHECK_FOR_IDLE_WHEN_IDLE; + } + else if(idleTime != 0) + { + long minIdleSetting = CHECK_FOR_IDLE_DEFAULT; + + if(!idleChangeListeners.isEmpty()) + minIdleSetting = + Collections.min(idleChangeListeners.values()); + + int newSetting = (int)(minIdleSetting - idleTime) + 1000; + + if(newSetting > 0) + idleStateCheckDelay = newSetting; + else + idleStateCheckDelay = CHECK_FOR_IDLE_DEFAULT; + } + else + { + idleStateCheckDelay = CHECK_FOR_IDLE_DEFAULT; + } + + // wait for the specified time + synchronized(this) + { + this.wait(idleStateCheckDelay); + } + } + catch(UnsatisfiedLinkError t) + { + logger.error("Missing native impl", t); + return; + } + catch(Throwable t) + { + logger.error("Error checking for idle", t); + } + } + } + + /** + * Delivers the specified event to all registered listeners. + * + * @param evt the <tt>SystemActivityEvent</tt> that we'd like delivered to + * all registered message listeners. + */ + protected void fireSystemActivityEvent(SystemActivityEvent evt) + { + int eventID = evt.getEventID(); + + // Add network activity info to track wake up problems. + if (logger.isInfoEnabled() + && ((eventID == SystemActivityEvent.EVENT_NETWORK_CHANGE) + || (eventID == SystemActivityEvent.EVENT_DNS_CHANGE))) + { + logger.info("Received system activity event: " + evt); + } + + if (eventID == SystemActivityEvent.EVENT_NETWORK_CHANGE) + { + // Give time to Java to dispatch same event and populate its network + // interfaces. + eventDispatcher.fireSystemActivityEvent(evt, 500); + } + else + eventDispatcher.fireSystemActivityEvent(evt); + } + + /** + * Delivers the specified event to all registered listeners. + * + * @param listener listener to inform + */ + protected void fireSystemIdleEvent(SystemActivityChangeListener listener) + { + SystemActivityEvent evt + = new SystemActivityEvent( + this, + SystemActivityEvent.EVENT_SYSTEM_IDLE); + + if (logger.isDebugEnabled()) + logger.debug("Dispatching SystemActivityEvent evt=" + evt); + + try + { + listener.activityChanged(evt); + } + catch (Throwable t) + { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + else + logger.error("Error delivering event", t); + } + } + + /** + * Delivers the specified event to listener. + * + * @param listener listener to inform + */ + protected void fireSystemIdleEndEvent( + SystemActivityChangeListener listener) + { + SystemActivityEvent evt + = new SystemActivityEvent( + this, + SystemActivityEvent.EVENT_SYSTEM_IDLE_END); + + if (logger.isDebugEnabled()) + logger.debug("Dispatching SystemActivityEvent evt=" + evt); + + try + { + listener.activityChanged(evt); + } + catch (Throwable t) + { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + else + logger.error("Error delivering event", t); + } + } + + /** + * Can check whether an event id is supported on + * current operation system. + * Simple return what is implemented in native, and checks + * are made when possible, for example linux cannot connect + * to NM through dbus. + * @param eventID the event to check. + * @return whether the supplied event id is supported. + */ + public boolean isSupported(int eventID) + { + if(OSUtils.IS_WINDOWS) + { + switch(eventID) + { + case SystemActivityEvent.EVENT_SLEEP: + case SystemActivityEvent.EVENT_WAKE: + case SystemActivityEvent.EVENT_NETWORK_CHANGE: + case SystemActivityEvent.EVENT_SYSTEM_IDLE: + case SystemActivityEvent.EVENT_SYSTEM_IDLE_END: + return SystemActivityNotifications.isLoaded(); + default: + return false; + } + } + else if(OSUtils.IS_MAC) + { + return SystemActivityNotifications.isLoaded(); + } + else if(OSUtils.IS_LINUX) + { + switch(eventID) + { + case SystemActivityEvent.EVENT_SLEEP: + case SystemActivityEvent.EVENT_NETWORK_CHANGE: + { + SystemActivityManager currentRunningManager + = getCurrentRunningManager(); + + return + (currentRunningManager == null) + ? false + : currentRunningManager.isConnected(); + } + case SystemActivityEvent.EVENT_SYSTEM_IDLE: + case SystemActivityEvent.EVENT_SYSTEM_IDLE_END: + return SystemActivityNotifications.isLoaded(); + default: + return false; + } + } + else if(OSUtils.IS_ANDROID) + { + return (eventID == SystemActivityEvent.EVENT_NETWORK_CHANGE); + } + else + { + return false; + } + } + + /** + * Returns or instantiate the manager. + * @return + */ + private SystemActivityManager getCurrentRunningManager() + { + if(currentRunningManager == null) + { + try + { + String className = null; + if(OSUtils.IS_LINUX) + { + className = SYSTEM_ACTIVITY_MANAGER_LINUX_CLASS; + } + else if(OSUtils.IS_ANDROID) + { + className = SYSTEM_ACTIVITY_MANAGER_ANDROID_CLASS; + } + + if(className != null) + currentRunningManager = (SystemActivityManager) + Class.forName(className).newInstance(); + } + catch(Throwable t) + { + logger.error("Error creating manager", t); + } + } + + return currentRunningManager; + } +} |