ddb506bfdbabe17d80e81b002742ad2604c5146b
[fonbot.git] / src / ro / ieval / fonbot / Utils.java
1 package ro.ieval.fonbot;
2
3 import static ro.ieval.fonbot.R.string.cannot_parse_count;
4 import static ro.ieval.fonbot.R.string.cannot_parse_interval;
5 import static ro.ieval.fonbot.R.string.cannot_parse_min_distance;
6 import static ro.ieval.fonbot.R.string.cannot_parse_min_time;
7 import static ro.ieval.fonbot.R.string.cannot_parse_port;
8 import static ro.ieval.fonbot.R.string.cannot_parse_provider_allowed_values_are;
9 import static ro.ieval.fonbot.R.string.command_disabled;
10 import static ro.ieval.fonbot.R.string.could_not_parse_argument_allowed_values_are;
11 import static ro.ieval.fonbot.R.string.could_not_parse_ms;
12 import static ro.ieval.fonbot.R.string.error_while_processing_command;
13 import static ro.ieval.fonbot.R.string.invalid_length_allowed_values_are;
14 import static ro.ieval.fonbot.R.string.invalid_ringer_mode_valid_values_are;
15 import static ro.ieval.fonbot.R.string.location_tracking_is_active;
16 import static ro.ieval.fonbot.R.string.messagetype_should_be_one_of;
17 import static ro.ieval.fonbot.R.string.no_such_command_command_list;
18 import static ro.ieval.fonbot.R.string.notification_disabled;
19 import static ro.ieval.fonbot.R.string.notification_enabled;
20 import static ro.ieval.fonbot.R.string.ringing;
21 import static ro.ieval.fonbot.R.string.security_exception;
22 import static ro.ieval.fonbot.R.string.the_polling_service_is_running;
23 import static ro.ieval.fonbot.R.string.the_second_argument_to_wipe_must_be;
24 import static ro.ieval.fonbot.R.string.unknown_command;
25 import static ro.ieval.fonbot.R.string.wipetype_should_be_one_of;
26
27 import java.net.MalformedURLException;
28 import java.net.URL;
29 import java.util.Arrays;
30 import java.util.Locale;
31
32 import org.eclipse.jdt.annotation.NonNull;
33 import org.eclipse.jdt.annotation.Nullable;
34
35 import ro.ieval.fonbot.Address.Protocol;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.SharedPreferences;
39 import android.database.Cursor;
40 import android.location.LocationManager;
41 import android.media.AudioManager;
42 import android.net.Uri;
43 import android.preference.PreferenceManager;
44 import android.provider.ContactsContract.PhoneLookup;
45 import android.telephony.SmsManager;
46 import android.util.Log;
47 import android.widget.Toast;
48
49 /*
50 * Copyright © 2013 Marius Gavrilescu
51 *
52 * This file is part of FonBot.
53 *
54 * FonBot is free software: you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
56 * the Free Software Foundation, either version 3 of the License, or
57 * (at your option) any later version.
58 *
59 * FonBot is distributed in the hope that it will be useful,
60 * but WITHOUT ANY WARRANTY; without even the implied warranty of
61 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62 * GNU General Public License for more details.
63 *
64 * You should have received a copy of the GNU General Public License
65 * along with FonBot. If not, see <http://www.gnu.org/licenses/>.
66 */
67
68 /**
69 * Utility functions and enums used in various places.
70 *
71 * @author Marius Gavrilescu <marius@ieval.ro>
72 */
73 public final class Utils {
74 /**
75 * Enum of all FonBot commands.
76 *
77 * @author Marius Gavrilescu <marius@ieval.ro>
78 */
79 @SuppressWarnings("javadoc")
80 public static enum Command{
81 TOAST, ECHO, SMS, FLASH, WIFI,
82 BLUETOOTH, DIAL, RING, SPEAK, VIBRATE,
83 DIALOG, LOCATION, NOLOCATION, RINGER, NCFILE,
84 PHOTO, SETNOTIFICATION, DELNOTIFICATION, SETPASSWORD, HELP,
85 WIPE, LOCK, VIEW, PLAY, PAUSE,
86 NEXT, PREV, BATT, CALLLOG, SMSLOG,
87 LS, RM, CONTACTS, DISABLE, ENABLE,
88 POLL, HANGUP, ANSWER, LAUNCH, DATA,
89 GPS, GLOCATION, REBOOT, SHUTDOWN, NOTIFY
90 }
91
92 /**
93 * Enum of all message types. Each message type is a kind of notification which can be enabled/disabled by the user and directed to a certain address.
94 *
95 * @author Marius Gavrilescu <marius@ieval.ro>
96 *
97 */
98 public static enum MessageType{
99 /** SMS notifications */
100 SMS,
101 /** Phone state (idle, offhook or ringing) notifications */
102 PHONE_STATE,
103 /** Lockscreen failed password notifications */
104 WATCH_LOGIN,
105 /** Device admin enable/disable notifications */
106 ADMIN,
107 /** Coarse battery status (low battery, ok battery) notifications */
108 BATTERY,
109 /** Fine battery status notifications */
110 BATTERY_CHANGED,
111 /** Headset plug/unplug notifications */
112 HEADSET
113 }
114
115 /**
116 * Enum of wipe types. The two defined types are the data wipe (which does not include the SD card) and the full wipe (which includes the SD card).
117 *
118 * @author Marius Gavrilescu <marius@ieval.ro>
119 */
120 public static enum WipeType{
121 /** Factory reset the phone, without touching the SD card */
122 DATA,
123 /** Factory reset the phone and wipe the SD card too */
124 FULL
125 }
126
127 /**
128 * Enum of ringer modes.
129 *
130 * @author Marius Gavrilescu <marius@ieval.ro>
131 */
132 public static enum RingerMode{
133 /** Sound is on */
134 NORMAL,
135 /** Sound is off, vibrate is on */
136 VIBRATE,
137 /** Sound is off, vibrate is off */
138 SILENT
139 }
140
141 /**
142 * Enum of location providers
143 *
144 * @author Marius Gavrilescu <marius@ieval.ro>
145 */
146 public static enum LocationProvider{
147 /** The network location provider */
148 NETWORK,
149 /** The GPS location provider */
150 GPS
151 }
152
153 /**
154 * Enum of toast lengths.
155 *
156 * @author Marius Gavrilescu <marius@ieval.ro>
157 */
158 private static enum ToastLength{
159 /** Long toast */
160 LONG,
161 /** Short toast */
162 SHORT
163 }
164
165 /**
166 * Enum of the values on and off. Used for boolean arguments.
167 *
168 * @author Marius Gavrilescu <marius@ieval.ro>
169 */
170 @SuppressWarnings("javadoc")
171 private static enum OnOff{
172 ON, OFF
173 }
174
175 /**
176 * Enum of ongoing event types
177 *
178 * @author Marius Gavrilescu <marius@ieval.ro>
179 */
180 public static enum OngoingEvent{
181 /** Location tracking is active. Registered by {@link Command#LOCATION}, unregistered by {@link Command#NOLOCATION} */
182 LOCATION(location_tracking_is_active),
183 /** The phone is ringing. Registered/unregistered by {@link Command#RING} */
184 RING(ringing),
185 /** The polling alarm is on. Registered/unregistered by {@link Command#POLL} */
186 POLL(the_polling_service_is_running);
187
188 /** String resource: the event description */
189 public final int resource;
190
191 /**
192 * Constructs an OngoingEvent from its event description.
193 *
194 * @param resource the event description
195 */
196 private OngoingEvent(final int resource) {
197 this.resource=resource;
198 }
199 }
200
201 /** Confirmation string for the {@link Command#WIPE WIPE} command. */
202 public static final String WIPE_CONFIRM_STRING="I am aware this cannot be undone";
203
204 /**
205 * Converts a Nullable object into a NonNull one.
206 *
207 * @param object the Nullable object to convert
208 * @return a NonNull object equivalent to the Nullable parameter
209 * @throws AssertionError if the given object is null
210 */
211 public static <T> T toNonNull(@Nullable T object) throws AssertionError{
212 if(object==null){
213 Log.wtf(Utils.class.getName(), "toNonNull called with null");
214 throw new AssertionError("Log.wtf did not terminate the process");
215 }
216 return object;
217 }
218
219 /**
220 * Join an array of Objects with elements separated by a separator into a single string.
221 *
222 * @param separator the separator
223 * @param offset the offset into the array
224 * @param args the array of Objects to join
225 * @return the joined string
226 */
227 public static String join(final String separator,final int offset,final Object[] args){
228 final StringBuilder sb=new StringBuilder(240);
229 sb.append(args[offset]);
230 for (int i = offset+1; i < args.length; i++) {
231 sb.append(separator);
232 sb.append(args[i]);
233 }
234 return toNonNull(sb.toString());
235 }
236
237 /**
238 * Join an array of Objects with elements separated by a separator into a single string.
239 *
240 * @param separator the separator
241 * @param args the array of objects to join
242 * @return the joined string
243 */
244 public static String join(final String separator, final Object[] args){
245 return join(separator,0,args);
246 }
247
248 /**
249 * Send a notification to the user.
250 *
251 * @param context Context instance
252 * @param type notification type
253 * @param resource String resource for the message text
254 */
255 public static void sendMessage(final Context context, final MessageType type, final int resource){
256 sendMessage(context, type, toNonNull(context.getString(resource)));
257 }
258
259 /**
260 * Send a notification to the user.
261 *
262 * @param context Context instance
263 * @param type notification type
264 * @param resource String resource for the message text
265 * @param args format parameters for the resource
266 */
267 public static void sendMessage(final Context context, final MessageType type, final int resource, final Object... args){
268 sendMessage(context, type, toNonNull(context.getString(resource, args)));
269 }
270
271 /**
272 * Send a message to a certain Address.
273 *
274 * @param context Context instance
275 * @param address destination Address
276 * @param resource String resource for the message text
277 */
278 public static void sendMessage(final Context context, final Address address, final int resource){
279 sendMessage(context, address, toNonNull(context.getString(resource)));
280 }
281
282 /**
283 * Send a message to a certain Address.
284 *
285 * @param context Context instance
286 * @param address destination Address
287 * @param resource String resource for the message text
288 * @param args format parameters for the resource
289 */
290 public static void sendMessage(final Context context, final Address address, final int resource, final Object... args){
291 sendMessage(context, address, toNonNull(context.getString(resource, args)));
292 }
293
294 /**
295 * Send a notification to the user.
296 *
297 * @param context Context instance
298 * @param type notification type
299 * @param msg the notification text
300 */
301 public static void sendMessage(final Context context, final MessageType type,final String msg){
302 final SharedPreferences sp=PreferenceManager.getDefaultSharedPreferences(context);
303 final String address=sp.getString(type.toString(),null);
304 if(address==null)
305 return;
306 sendMessage(context, new Address(address), msg);
307 }
308
309 /**
310 * Send a message to a certain Address.
311 *
312 * @param context Context instance
313 * @param address destination Address
314 * @param message the message text
315 */
316 public static void sendMessage(final Context context, final Address address, final String message){
317 switch(address.protocol){
318 case HTTP:
319 new HttpCallExecutableRunnable("/send", toNonNull(Arrays.asList(
320 new Header("X-Destination", toNonNull(address.data)))), context, null, message).execute();
321 break;
322
323 case SMS:
324 SmsManager.getDefault().sendTextMessage(address.data, null, message, null, null);
325 break;
326
327 case LOCAL:
328 final Intent intent = new Intent(FonBotLocalActivity.RESPONSE_RECEIVED_ACTION);
329 intent.putExtra(FonBotLocalActivity.EXTRA_RESPONSE, message);
330 context.sendBroadcast(intent);
331 break;
332
333 case NULL:
334 break;//blackhole
335 }
336 }
337
338 /**
339 * Splits a string into words.
340 *
341 * @param string the string
342 * @return an array of words
343 */
344 public static String[] shellwords(final String string){
345 return toNonNull(string.split("[ ]+(?=([^\"]*\"[^\"]*\")*[^\"]*$)"));//TODO: Make this handle backslash escapes
346 }
347
348 /**
349 * Returns the name associated with a phone number.
350 *
351 * @param context Context instance
352 * @param number phone number to search for
353 * @return the name associated with this number, or null if the number was not found in the contacts.
354 */
355 public static @Nullable String callerId(final Context context, final String number){
356 final Cursor cursor=context.getContentResolver().query(
357 Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)),
358 new String[]{PhoneLookup.DISPLAY_NAME},
359 null,
360 null,
361 null);
362
363 if(cursor.moveToFirst()){
364 final String name=cursor.getString(0);
365 cursor.close();
366 return name;
367 }
368 cursor.close();
369 return null;
370 }
371
372 /**
373 * Registers an ongoing event.
374 *
375 * @param context Context instance
376 * @param event event to register
377 */
378 public static void registerOngoing(final Context context, final OngoingEvent event){
379 final Intent intent=new Intent(context, FonBotMainService.class);
380 intent.setAction(FonBotMainService.ACTION_PUT_ONGOING);
381 intent.putExtra(FonBotMainService.EXTRA_ONGOING_ID, event.ordinal());
382 context.startService(intent);
383 }
384
385 /**
386 * Unregisters an ongoing event
387 *
388 * @param context Context instance
389 * @param event event to unregister
390 */
391 public static void unregisterOngoing(final Context context, final OngoingEvent event){
392 final Intent intent=new Intent(context, FonBotMainService.class);
393 intent.setAction(FonBotMainService.ACTION_DELETE_ONGOING);
394 intent.putExtra(FonBotMainService.EXTRA_ONGOING_ID, event.ordinal());
395 context.startService(intent);
396 }
397
398 /**
399 * Gets the server URL according to the user preferences.
400 *
401 * @param context Context instance
402 * @param path URL path
403 * @return the server URL
404 * @throws MalformedURLException if the user preferences create an invalid URL
405 */
406 public static URL getServerURL(final Context context, final String path) throws MalformedURLException{
407 final String hostname=PreferenceManager.getDefaultSharedPreferences(context).getString("hostname", "fonbot.ieval.ro");
408 final int port=Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(context).getString("port", "7777"));
409 final URL url=new URL("https", hostname, port, path);
410 return url;
411 }
412
413 /**
414 * Poll the server for pending commands.
415 *
416 * @param context Context instance
417 */
418 public static void pollServer(final Context context){
419 new HttpCallExecutableRunnable("/get", null, context, new PollResultCallback(context)).execute();
420 }
421
422 /**
423 * Executes a given command
424 *
425 * @param context Context instance
426 * @param cmd Command to execute
427 * @param args arguments for the command
428 * @param replyTo Address to send replies to
429 */
430 private static void processCommand(final Context context, final Command cmd,final String[] args,final Address replyTo){
431 if(Heavy.isCommandDisabled(context, cmd)){
432 sendMessage(context, replyTo, command_disabled);
433 return;
434 }
435
436 switch(cmd){
437 case TOAST:
438 if(args.length < 1 || args.length > 2){
439 Heavy.help(context, replyTo, toNonNull(Command.TOAST));
440 break;
441 }
442
443 if(args.length==1)
444 Heavy.toast(context, replyTo, toNonNull(args[0]));
445 else {
446 try {
447 switch(ToastLength.valueOf(args[1].toUpperCase(Locale.ENGLISH))){
448 case LONG:
449 Heavy.toast(context, replyTo, toNonNull(args[0]), Toast.LENGTH_LONG);
450 break;
451 case SHORT:
452 Heavy.toast(context, replyTo, toNonNull(args[0]), Toast.LENGTH_SHORT);
453 }
454 } catch(IllegalArgumentException e){
455 sendMessage(context, replyTo, invalid_length_allowed_values_are, join(", ",toNonNull(ToastLength.values())));
456 }
457 }
458 break;
459
460 case ECHO:
461 if(args.length==0){
462 Heavy.help(context, replyTo, toNonNull(Command.ECHO));
463 break;
464 }
465 sendMessage(context, replyTo, join(" ",args));
466 break;
467
468 case SMS:
469 if(args.length < 2){
470 Heavy.help(context, replyTo, toNonNull(Command.SMS));
471 break;
472 }
473 Heavy.sms(context, replyTo, toNonNull(args[0]), join(" ", 1, args));
474 break;
475
476 case FLASH:
477 if(args.length != 1){
478 Heavy.help(context, replyTo, toNonNull(Command.FLASH));
479 break;
480 }
481
482 try {
483 Heavy.flash(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
484 } catch(IllegalArgumentException e) {
485 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
486 }
487 break;
488
489 case WIFI:
490 if(args.length>1){
491 Heavy.help(context, replyTo, toNonNull(Command.WIFI));
492 break;
493 }
494 if(args.length==0)
495 Heavy.wifi(context, replyTo);
496 else {
497 try {
498 Heavy.wifi(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
499 } catch(IllegalArgumentException e) {
500 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
501 }
502 }
503 break;
504
505 case BLUETOOTH:
506 if(args.length>1){
507 Heavy.help(context, replyTo, toNonNull(Command.BLUETOOTH));
508 break;
509 }
510 if(args.length==0)
511 Heavy.bluetooth(context, replyTo);
512 else {
513 try {
514 Heavy.bluetooth(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
515 } catch(IllegalArgumentException e) {
516 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
517 }
518 }
519 break;
520
521 case DIAL:
522 if(args.length!=1){
523 Heavy.help(context, replyTo, toNonNull(Command.DIAL));
524 break;
525 }
526 Heavy.dial(context, replyTo, toNonNull(args[0]));
527 break;
528
529 case RING:
530 if(args.length>1){
531 Heavy.help(context, replyTo, toNonNull(Command.RING));
532 break;
533 }
534 if(args.length==0)
535 Heavy.ring(context, replyTo);
536 else {
537 try {
538 Heavy.ring(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
539 } catch(IllegalArgumentException e){
540 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
541 }
542 }
543 break;
544
545 case SPEAK:
546 if(args.length==0){
547 Heavy.help(context, replyTo, toNonNull(Command.SPEAK));
548 break;
549 }
550 Heavy.speak(context, replyTo, join(" ",args));
551 break;
552
553 case VIBRATE:
554 if(args.length!=1){
555 Heavy.help(context, replyTo, toNonNull(Command.VIBRATE));
556 break;
557 }
558 final long ms;
559 try{
560 ms=Long.parseLong(args[0]);
561 } catch(NumberFormatException e){
562 sendMessage(context, replyTo, could_not_parse_ms);
563 break;
564 }
565 Heavy.vibrate(context, replyTo, ms);
566 break;
567
568 case DIALOG://TODO: Should add an edittext
569 if(args.length<1){
570 Heavy.help(context, replyTo, toNonNull(Command.DIALOG));
571 break;
572 }
573 final String[] buttons=new String[args.length-1];
574 System.arraycopy(args,1,buttons,0,buttons.length);
575 Heavy.dialog(context, replyTo, toNonNull(args[0]), buttons);
576 break;
577
578 case LOCATION:
579 if(args.length>3||args.length<1){
580 Heavy.help(context, replyTo, toNonNull(Command.LOCATION));
581 break;
582 }
583
584 final @NonNull String provider;
585 try{
586 switch(LocationProvider.valueOf(args[0].toUpperCase(Locale.ENGLISH))){
587 case GPS:
588 provider=toNonNull(LocationManager.GPS_PROVIDER);
589 break;
590 case NETWORK:
591 default:
592 provider=toNonNull(LocationManager.NETWORK_PROVIDER);
593 break;
594 }
595 } catch(IllegalArgumentException e){
596 sendMessage(context, replyTo, cannot_parse_provider_allowed_values_are, join(", ",toNonNull(LocationProvider.values())));
597 break;
598 }
599
600 final long minTime;
601 final float minDistance;
602
603 if(args.length>1)
604 try{
605 minTime=Long.parseLong(args[1]);
606 } catch (NumberFormatException e){
607 sendMessage(context, replyTo, cannot_parse_min_time);
608 break;
609 }
610 else
611 minTime=500;
612
613 if(args.length>2)
614 try{
615 minDistance=Float.parseFloat(args[2]);
616 } catch (NumberFormatException e){
617 sendMessage(context, replyTo, cannot_parse_min_distance);
618 break;
619 }
620 else
621 minDistance=0;
622 Heavy.location(context, replyTo, provider, minTime, minDistance);
623 break;
624
625 case NOLOCATION:
626 Heavy.nolocation(context, replyTo);
627 break;
628
629 case RINGER:
630 if(args.length>1){
631 Heavy.help(context, replyTo, toNonNull(Command.RINGER));
632 break;
633 }
634 if(args.length==0)
635 Heavy.ringer(context, replyTo);
636 else{
637 try{
638 final RingerMode rm=RingerMode.valueOf(args[0].toUpperCase(Locale.ENGLISH));
639 switch(rm){
640 case NORMAL:
641 Heavy.ringer(context, replyTo, AudioManager.RINGER_MODE_NORMAL);
642 break;
643 case VIBRATE:
644 Heavy.ringer(context, replyTo, AudioManager.RINGER_MODE_VIBRATE);
645 break;
646 case SILENT:
647 Heavy.ringer(context, replyTo, AudioManager.RINGER_MODE_SILENT);
648 break;
649 }
650 } catch (IllegalArgumentException e){
651 Utils.sendMessage(context, replyTo, invalid_ringer_mode_valid_values_are, join(", ",toNonNull(RingerMode.values())));
652 }
653 }
654 break;
655
656 case NCFILE:
657 if(args.length!=3){
658 Heavy.help(context, replyTo, toNonNull(Command.NCFILE));
659 break;
660 }
661
662 final int ncfilePort;
663 try{
664 ncfilePort=Integer.parseInt(args[2]);
665 } catch (NumberFormatException e){
666 sendMessage(context, replyTo, cannot_parse_port);
667 break;
668 }
669 Heavy.ncfile(context, replyTo, toNonNull(args[0]), toNonNull(args[1]), ncfilePort);
670 break;
671
672 case PHOTO:
673 if(args.length!=2){
674 Heavy.help(context, replyTo, toNonNull(Command.PHOTO));
675 break;
676 }
677 final int photoPort;
678 try{
679 photoPort=Integer.parseInt(args[1]);
680 } catch (NumberFormatException e){
681 sendMessage(context, replyTo, cannot_parse_port);
682 break;
683 }
684 Heavy.photo(context, replyTo, toNonNull(args[0]), photoPort);
685 break;
686
687 case SETNOTIFICATION:
688 if(args.length!=1){
689 Heavy.help(context, replyTo, toNonNull(Command.SETNOTIFICATION));
690 break;
691 }
692
693 try{
694 PreferenceManager.getDefaultSharedPreferences(context).edit()
695 .putString(MessageType.valueOf(args[0].toUpperCase(Locale.ENGLISH)).toString(), replyTo.toString())
696 .commit();
697 sendMessage(context, replyTo, notification_enabled);
698 } catch (IllegalArgumentException e){
699 sendMessage(context, replyTo, messagetype_should_be_one_of, join(", ",toNonNull(MessageType.values())));
700 break;
701 }
702
703 break;
704
705 case DELNOTIFICATION:
706 if(args.length!=1){
707 Heavy.help(context, replyTo, toNonNull(Command.DELNOTIFICATION));
708 break;
709 }
710
711 try{
712 PreferenceManager.getDefaultSharedPreferences(context).edit()
713 .remove(MessageType.valueOf(args[0].toUpperCase(Locale.ENGLISH)).toString())
714 .commit();
715 sendMessage(context, replyTo, notification_disabled);
716 } catch (IllegalArgumentException e){
717 sendMessage(context, replyTo, messagetype_should_be_one_of, join(", ",toNonNull(MessageType.values())));
718 break;
719 }
720
721
722 break;
723 case SETPASSWORD:
724 if(args.length > 1){
725 Heavy.help(context, replyTo, toNonNull(Command.SETPASSWORD));
726 break;
727 }
728
729 try{
730 if(args.length==0)
731 Heavy.setPassword(context, replyTo);
732 else
733 Heavy.setPassword(context, replyTo, toNonNull(args[0]));
734 } catch (SecurityException e){
735 sendMessage(context, replyTo, security_exception+e.getMessage());
736 }
737 break;
738
739 case WIPE:
740 if(args.length!=2){
741 Heavy.help(context, replyTo, toNonNull(Command.WIPE));
742 break;
743 }
744
745 if(!args[1].equalsIgnoreCase(WIPE_CONFIRM_STRING)){
746 sendMessage(context, replyTo, the_second_argument_to_wipe_must_be, WIPE_CONFIRM_STRING);
747 break;
748 }
749
750 try{
751 Heavy.wipe(context, toNonNull(WipeType.valueOf(args[0].toUpperCase(Locale.ENGLISH))));
752 } catch (IllegalArgumentException e){
753 sendMessage(context, replyTo, wipetype_should_be_one_of, join (", ",toNonNull(WipeType.values())));
754 } catch (SecurityException e){
755 sendMessage(context, replyTo, security_exception, e.getMessage());
756 }
757 break;
758
759 case LOCK:
760 try{
761 Heavy.lock(context, replyTo);
762 } catch (SecurityException e){
763 sendMessage(context, replyTo, security_exception, e.getMessage());
764 }
765 break;
766
767 case VIEW:
768 if(args.length!=1){
769 Heavy.help(context, replyTo, toNonNull(Command.VIEW));
770 break;
771 }
772
773 Heavy.view(context, replyTo, toNonNull(Uri.parse(args[0])));
774 break;
775
776 case PLAY:
777 Heavy.musicPlayerCommand(context, replyTo, "play");
778 break;
779
780 case PAUSE:
781 Heavy.musicPlayerCommand(context, replyTo, "pause");
782 break;
783
784 case NEXT:
785 Heavy.musicPlayerCommand(context, replyTo, "next");
786 break;
787
788 case PREV:
789 Heavy.musicPlayerCommand(context, replyTo, "previous");
790 break;
791
792 case BATT:
793 Heavy.batt(context, replyTo);
794 break;
795
796 case CALLLOG:
797 if (args.length > 1) {
798 Heavy.help(context, replyTo, toNonNull(Command.CALLLOG));
799 break;
800 }
801
802 if (args.length == 0)
803 Heavy.calllog(context, replyTo, 5);
804 else {
805 try {
806 Heavy.calllog(context, replyTo, Integer.parseInt(args[0]));
807 } catch (IllegalArgumentException e){
808 sendMessage(context, replyTo, cannot_parse_count);
809 }
810 }
811 break;
812
813 case SMSLOG:
814 if (args.length > 1) {
815 Heavy.help(context, replyTo, toNonNull(Command.SMSLOG));
816 break;
817 }
818
819 if (args.length == 0)
820 Heavy.smslog(context, replyTo, 5);
821 else {
822 try {
823 Heavy.smslog(context, replyTo, Integer.parseInt(args[0]));
824 } catch (IllegalArgumentException e) {
825 sendMessage(context, replyTo, cannot_parse_count);
826 }
827 }
828 break;
829
830 case HELP:
831 if(args.length != 1){
832 Heavy.help(context, replyTo, toNonNull(Command.HELP));
833 break;
834 }
835
836 try {
837 Heavy.help(context, replyTo, toNonNull(Command.valueOf(args[0].toUpperCase(Locale.ENGLISH))));
838 } catch (IllegalArgumentException e) {
839 sendMessage(context, replyTo, no_such_command_command_list, join(", ", toNonNull(Command.values())));
840 }
841 break;
842
843 case LS:
844 if(args.length != 1){
845 Heavy.help(context, replyTo, toNonNull(Command.LS));
846 break;
847 }
848
849 Heavy.ls(context, replyTo, toNonNull(args[0]));
850 break;
851
852 case RM:
853 if(args.length != 1){
854 Heavy.help(context, replyTo, toNonNull(Command.RM));
855 break;
856 }
857
858 Heavy.rm(context, replyTo, toNonNull(args[0]));
859 break;
860
861 case CONTACTS:
862 if(args.length != 1){
863 Heavy.help(context, replyTo, toNonNull(Command.CONTACTS));
864 break;
865 }
866
867 Heavy.contacts(context, replyTo, toNonNull(args[0]));
868 break;
869
870 case DISABLE:
871 if(replyTo.protocol != Protocol.LOCAL || args.length != 1){
872 Heavy.help(context, replyTo, toNonNull(Command.DISABLE));
873 break;
874 }
875
876 try{
877 Heavy.disable(context, replyTo, toNonNull(Command.valueOf(args[0].toUpperCase(Locale.ENGLISH))));
878 } catch (IllegalArgumentException e){
879 sendMessage(context, replyTo, no_such_command_command_list, join(", ", toNonNull(Command.values())));
880 }
881 break;
882
883 case ENABLE:
884 if(replyTo.protocol != Protocol.LOCAL || args.length != 1){
885 Heavy.help(context, replyTo, toNonNull(Command.ENABLE));
886 break;
887 }
888
889 try{
890 Heavy.enable(context, replyTo, toNonNull(Command.valueOf(args[0].toUpperCase(Locale.ENGLISH))));
891 } catch (IllegalArgumentException e){
892 sendMessage(context, replyTo, no_such_command_command_list, join(", ", toNonNull(Command.values())));
893 }
894 break;
895
896 case POLL:
897 if(args.length>1){
898 Heavy.help(context, replyTo, toNonNull(Command.POLL));
899 break;
900 }
901
902 if(args.length==0){
903 Heavy.poll(context, replyTo);
904 break;
905 }
906
907 final long interval;
908 try{
909 interval=Long.parseLong(args[0]);
910 } catch(NumberFormatException e){
911 sendMessage(context, replyTo, cannot_parse_interval);
912 break;
913 }
914
915 Heavy.poll(context, replyTo, interval);
916 break;
917
918 case HANGUP:
919 Heavy.hangup(context, replyTo);
920 break;
921
922 case ANSWER:
923 Heavy.answer(context, replyTo);
924 break;
925
926 case LAUNCH:
927 if(args.length!=1){
928 Heavy.help(context, replyTo, toNonNull(Command.LAUNCH));
929 break;
930 }
931 Heavy.launch(context, replyTo, toNonNull(args[0]));
932 break;
933
934 case DATA:
935 if(args.length>1){
936 Heavy.help(context, replyTo, toNonNull(Command.DATA));
937 break;
938 }
939
940 if(args.length==0){
941 Heavy.data(context, replyTo);
942 break;
943 }
944 try {
945 Heavy.data(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
946 } catch(IllegalArgumentException e) {
947 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
948 }
949 break;
950
951 case GPS:
952 if(args.length>1){
953 Heavy.help(context, replyTo, toNonNull(Command.GPS));
954 break;
955 }
956
957 if(args.length==0){
958 Heavy.gps(context, replyTo);
959 break;
960 }
961
962 try {
963 Heavy.gps(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
964 } catch(IllegalArgumentException e) {
965 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
966 }
967 break;
968
969 case GLOCATION:
970 if(args.length>1){
971 Heavy.help(context, replyTo, toNonNull(Command.GLOCATION));
972 break;
973 }
974
975 if(args.length==0){
976 Heavy.glocation(context, replyTo);
977 break;
978 }
979
980 try {
981 Heavy.glocation(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
982 } catch(IllegalArgumentException e) {
983 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
984 }
985 break;
986
987 case REBOOT:
988 if(args.length>1){
989 Heavy.help(context, replyTo, toNonNull(Command.REBOOT));
990 break;
991 }
992
993 Heavy.reboot(context, replyTo, args.length==0?null:args[0]);
994 break;
995
996 case SHUTDOWN:
997 //TODO: implement command
998 break;
999
1000 case NOTIFY:
1001 if(args.length!=1 && args.length!=3){
1002 Heavy.help(context, replyTo, toNonNull(Command.NOTIFY));
1003 }
1004
1005 final int id;
1006 try{
1007 id=Integer.parseInt(args[0]);
1008 } catch (NumberFormatException e){
1009 sendMessage(context, replyTo, R.string.could_not_parse_id);
1010 break;
1011 }
1012
1013 if(args.length==1)
1014 Heavy.notify(context, replyTo, id);
1015 else
1016 Heavy.notify(context, replyTo, id, toNonNull(args[1]), toNonNull(args[2]));
1017 break;
1018 }
1019
1020 }
1021
1022 /**
1023 * Executes a given command
1024 *
1025 * @param context Context instance
1026 * @param cmd Command to execute
1027 * @param args arguments for the command
1028 * @param replyTo Address to send replies to
1029 */
1030 public static void processCommand(final Context context, final String cmd,final String[] args,final Address replyTo){
1031 final @NonNull Command command;
1032 try{
1033 command=toNonNull(Command.valueOf(cmd.toUpperCase(Locale.ENGLISH)));
1034 } catch (IllegalArgumentException e){
1035 sendMessage(context, replyTo, unknown_command, cmd.toUpperCase(Locale.ENGLISH), e.getMessage());
1036 return;
1037 }
1038
1039 try{
1040 processCommand(context, command,args,replyTo);
1041 } catch(Exception e){
1042 sendMessage(context, replyTo, error_while_processing_command, e.getClass().getName(), e.getMessage());
1043 Log.w(Utils.class.getName(), "Error while processing command", e);
1044 }
1045 }
1046 }
This page took 0.048297 seconds and 3 git commands to generate.