Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 package org.ros.android;
00018
00019 import com.google.common.base.Preconditions;
00020
00021 import android.app.AlertDialog;
00022 import android.app.Notification;
00023 import android.app.PendingIntent;
00024 import android.app.Service;
00025 import android.content.DialogInterface;
00026 import android.content.DialogInterface.OnClickListener;
00027 import android.content.Intent;
00028 import android.net.wifi.WifiManager;
00029 import android.net.wifi.WifiManager.WifiLock;
00030 import android.os.AsyncTask;
00031 import android.os.Binder;
00032 import android.os.Handler;
00033 import android.os.IBinder;
00034 import android.os.PowerManager;
00035 import android.os.PowerManager.WakeLock;
00036 import android.util.Log;
00037 import android.view.WindowManager;
00038 import android.widget.Toast;
00039 import org.ros.RosCore;
00040 import org.ros.android.android_10.R;
00041 import org.ros.address.InetAddressFactory;
00042 import org.ros.concurrent.ListenerGroup;
00043 import org.ros.concurrent.SignalRunnable;
00044 import org.ros.exception.RosRuntimeException;
00045 import org.ros.node.DefaultNodeMainExecutor;
00046 import org.ros.node.NodeConfiguration;
00047 import org.ros.node.NodeListener;
00048 import org.ros.node.NodeMain;
00049 import org.ros.node.NodeMainExecutor;
00050
00051 import java.net.URI;
00052 import java.util.Collection;
00053 import java.util.concurrent.ExecutionException;
00054 import java.util.concurrent.ScheduledExecutorService;
00055
00059 public class NodeMainExecutorService extends Service implements NodeMainExecutor {
00060
00061 private static final String TAG = "NodeMainExecutorService";
00062
00063
00064 private static final int ONGOING_NOTIFICATION = 1;
00065
00066 public static final String ACTION_START = "org.ros.android.ACTION_START_NODE_RUNNER_SERVICE";
00067 public static final String ACTION_SHUTDOWN = "org.ros.android.ACTION_SHUTDOWN_NODE_RUNNER_SERVICE";
00068 public static final String EXTRA_NOTIFICATION_TITLE = "org.ros.android.EXTRA_NOTIFICATION_TITLE";
00069 public static final String EXTRA_NOTIFICATION_TICKER = "org.ros.android.EXTRA_NOTIFICATION_TICKER";
00070
00071 private final NodeMainExecutor nodeMainExecutor;
00072 private final IBinder binder;
00073 private final ListenerGroup<NodeMainExecutorServiceListener> listeners;
00074
00075 private Handler handler;
00076 private WakeLock wakeLock;
00077 private WifiLock wifiLock;
00078 private RosCore rosCore;
00079 private URI masterUri;
00080 private String rosHostname;
00081
00086 public class LocalBinder extends Binder {
00087 public NodeMainExecutorService getService() {
00088 return NodeMainExecutorService.this;
00089 }
00090 }
00091
00092 public NodeMainExecutorService() {
00093 super();
00094 rosHostname = null;
00095 nodeMainExecutor = DefaultNodeMainExecutor.newDefault();
00096 binder = new LocalBinder();
00097 listeners =
00098 new ListenerGroup<NodeMainExecutorServiceListener>(
00099 nodeMainExecutor.getScheduledExecutorService());
00100 }
00101
00102 @Override
00103 public void onCreate() {
00104 handler = new Handler();
00105 PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
00106 wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
00107 wakeLock.acquire();
00108 int wifiLockType = WifiManager.WIFI_MODE_FULL;
00109 try {
00110 wifiLockType = WifiManager.class.getField("WIFI_MODE_FULL_HIGH_PERF").getInt(null);
00111 } catch (Exception e) {
00112
00113 Log.w(TAG, "Unable to acquire high performance wifi lock.");
00114 }
00115 WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
00116 wifiLock = wifiManager.createWifiLock(wifiLockType, TAG);
00117 wifiLock.acquire();
00118 }
00119
00120 @Override
00121 public void execute(NodeMain nodeMain, NodeConfiguration nodeConfiguration,
00122 Collection<NodeListener> nodeListeneners) {
00123 nodeMainExecutor.execute(nodeMain, nodeConfiguration, nodeListeneners);
00124 }
00125
00126 @Override
00127 public void execute(NodeMain nodeMain, NodeConfiguration nodeConfiguration) {
00128 execute(nodeMain, nodeConfiguration, null);
00129 }
00130
00131 @Override
00132 public ScheduledExecutorService getScheduledExecutorService() {
00133 return nodeMainExecutor.getScheduledExecutorService();
00134 }
00135
00136 @Override
00137 public void shutdownNodeMain(NodeMain nodeMain) {
00138 nodeMainExecutor.shutdownNodeMain(nodeMain);
00139 }
00140
00141 @Override
00142 public void shutdown() {
00143 handler.post(new Runnable() {
00144 @Override
00145 public void run() {
00146 AlertDialog.Builder builder = new AlertDialog.Builder(NodeMainExecutorService.this);
00147 builder.setMessage("Continue shutting down?");
00148 builder.setPositiveButton("Shutdown", new OnClickListener() {
00149 @Override
00150 public void onClick(DialogInterface dialog, int which) {
00151 forceShutdown();
00152 }
00153 });
00154 builder.setNegativeButton("Cancel", new OnClickListener() {
00155 @Override
00156 public void onClick(DialogInterface dialog, int which) {
00157 }
00158 });
00159 AlertDialog alertDialog = builder.create();
00160 alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
00161 alertDialog.show();
00162 }
00163 });
00164 }
00165
00166 public void forceShutdown() {
00167 signalOnShutdown();
00168 stopForeground(true);
00169 stopSelf();
00170 }
00171
00172 public void addListener(NodeMainExecutorServiceListener listener) {
00173 listeners.add(listener);
00174 }
00175
00176 public void removeListener(NodeMainExecutorServiceListener listener)
00177 {
00178 listeners.remove(listener);
00179 }
00180
00181 private void signalOnShutdown() {
00182 listeners.signal(new SignalRunnable<NodeMainExecutorServiceListener>() {
00183 @Override
00184 public void run(NodeMainExecutorServiceListener nodeMainExecutorServiceListener) {
00185 nodeMainExecutorServiceListener.onShutdown(NodeMainExecutorService.this);
00186 }
00187 });
00188 }
00189
00190 @Override
00191 public void onDestroy() {
00192 toast("Shutting down...");
00193 nodeMainExecutor.shutdown();
00194 if (rosCore != null) {
00195 rosCore.shutdown();
00196 }
00197 if (wakeLock.isHeld()) {
00198 wakeLock.release();
00199 }
00200 if (wifiLock.isHeld()) {
00201 wifiLock.release();
00202 }
00203 super.onDestroy();
00204 }
00205
00206 @Override
00207 public int onStartCommand(Intent intent, int flags, int startId) {
00208 if (intent.getAction() == null) {
00209 return START_NOT_STICKY;
00210 }
00211 if (intent.getAction().equals(ACTION_START)) {
00212 Preconditions.checkArgument(intent.hasExtra(EXTRA_NOTIFICATION_TICKER));
00213 Preconditions.checkArgument(intent.hasExtra(EXTRA_NOTIFICATION_TITLE));
00214 Notification notification =
00215 new Notification(R.mipmap.icon, intent.getStringExtra(EXTRA_NOTIFICATION_TICKER),
00216 System.currentTimeMillis());
00217 Intent notificationIntent = new Intent(this, NodeMainExecutorService.class);
00218 notificationIntent.setAction(NodeMainExecutorService.ACTION_SHUTDOWN);
00219 PendingIntent pendingIntent = PendingIntent.getService(this, 0, notificationIntent, 0);
00220 notification.setLatestEventInfo(this, intent.getStringExtra(EXTRA_NOTIFICATION_TITLE),
00221 "Tap to shutdown.", pendingIntent);
00222 startForeground(ONGOING_NOTIFICATION, notification);
00223 }
00224 if (intent.getAction().equals(ACTION_SHUTDOWN)) {
00225 shutdown();
00226 }
00227 return START_NOT_STICKY;
00228 }
00229
00230 @Override
00231 public IBinder onBind(Intent intent) {
00232 return binder;
00233 }
00234
00235 public URI getMasterUri() {
00236 return masterUri;
00237 }
00238
00239 public void setMasterUri(URI uri) {
00240 masterUri = uri;
00241 }
00242
00243 public void setRosHostname(String hostname) {
00244 rosHostname = hostname;
00245 }
00246
00247 public String getRosHostname() {
00248 return rosHostname;
00249 }
00255 @Deprecated
00256 public void startMaster() {
00257 startMaster(true);
00258 }
00259
00264 public void startMaster(boolean isPrivate) {
00265 AsyncTask<Boolean, Void, URI> task = new AsyncTask<Boolean, Void, URI>() {
00266 @Override
00267 protected URI doInBackground(Boolean[] params) {
00268 NodeMainExecutorService.this.startMasterBlocking(params[0]);
00269 return NodeMainExecutorService.this.getMasterUri();
00270 }
00271 };
00272 task.execute(isPrivate);
00273 try {
00274 task.get();
00275 } catch (InterruptedException e) {
00276 throw new RosRuntimeException(e);
00277 } catch (ExecutionException e) {
00278 throw new RosRuntimeException(e);
00279 }
00280 }
00281
00286 private void startMasterBlocking(boolean isPrivate) {
00287 if (isPrivate) {
00288 rosCore = RosCore.newPrivate();
00289 } else if (rosHostname != null) {
00290 rosCore = RosCore.newPublic(rosHostname, 11311);
00291 } else {
00292 rosCore = RosCore.newPublic(11311);
00293 }
00294 rosCore.start();
00295 try {
00296 rosCore.awaitStart();
00297 } catch (Exception e) {
00298 throw new RosRuntimeException(e);
00299 }
00300 masterUri = rosCore.getUri();
00301 }
00302
00303 public void toast(final String text) {
00304 handler.post(new Runnable() {
00305 @Override
00306 public void run() {
00307 Toast.makeText(NodeMainExecutorService.this, text, Toast.LENGTH_SHORT).show();
00308 }
00309 });
00310 }
00311 }