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