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