PageRenderTime 58ms CodeModel.GetById 20ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 1ms

/shell/src/com/google/marvin/shell/AuditoryWidgets.java

http://eyes-free.googlecode.com/
Java | 401 lines | 313 code | 36 blank | 52 comment | 83 complexity | f07965c81afe86d48b7f954674240c37 MD5 | raw file
  1/*
  2 * Copyright (C) 2010 Google Inc.
  3 *
  4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5 * use this file except in compliance with the License. You may obtain a copy of
  6 * the License at
  7 *
  8 * http://www.apache.org/licenses/LICENSE-2.0
  9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 13 * License for the specific language governing permissions and limitations under
 14 * the License.
 15 */
 16
 17package com.google.marvin.shell;
 18
 19import android.bluetooth.BluetoothAdapter;
 20import android.content.ActivityNotFoundException;
 21import android.content.BroadcastReceiver;
 22import android.content.ContentResolver;
 23import android.content.Context;
 24import android.content.Intent;
 25import android.content.IntentFilter;
 26import android.net.ConnectivityManager;
 27import android.net.NetworkInfo;
 28import android.net.Uri;
 29import android.net.wifi.WifiInfo;
 30import android.net.wifi.WifiManager;
 31import android.os.BatteryManager;
 32import android.provider.Settings.SettingNotFoundException;
 33import android.provider.Settings.System;
 34import android.speech.RecognizerIntent;
 35import android.speech.tts.TextToSpeech;
 36import android.telephony.PhoneStateListener;
 37import android.telephony.ServiceState;
 38import android.telephony.TelephonyManager;
 39
 40import java.lang.reflect.Method;
 41import java.text.SimpleDateFormat;
 42import java.util.Calendar;
 43import java.util.HashMap;
 44
 45// Most of the logic for determining strength levels is based on the code here:
 46// http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=services/java/com/android/server/status/StatusBarPolicy.java
 47
 48/**
 49 * Collection of one shot speech widgets for the home screen
 50 *
 51 * @author clchen@google.com (Charles L. Chen)
 52 * @author credo@google.com (Tim Credo)
 53 */
 54public class AuditoryWidgets {
 55    private TextToSpeech tts;
 56
 57    private MarvinShell parent;
 58
 59    private Guide guide;
 60
 61    private boolean useGpsThisTime;
 62
 63    private int voiceSignalStrength;
 64
 65    private int callState = TelephonyManager.CALL_STATE_IDLE;
 66
 67    /**
 68     * Map user-facing widget descriptions to the strings used to indicate them
 69     * in XML.
 70     */
 71    public HashMap<String, String> descriptionToWidget;
 72
 73    public AuditoryWidgets(TextToSpeech theTts, MarvinShell shell) {
 74        tts = theTts;
 75        parent = shell;
 76        useGpsThisTime = true;
 77        voiceSignalStrength = 0;
 78        TelephonyManager tm = (TelephonyManager) parent.getSystemService(Context.TELEPHONY_SERVICE);
 79        tm.listen(new PhoneStateListener() {
 80            private boolean inService = true;
 81
 82            @Override
 83            public void onServiceStateChanged(ServiceState service) {
 84                if (service.getState() != ServiceState.STATE_IN_SERVICE) {
 85                    inService = false;
 86                } else {
 87                    inService = true;
 88                }
 89            }
 90
 91            @Override
 92            public void onSignalStrengthChanged(int asu) {
 93                if ((asu == -1) || !inService) {
 94                    voiceSignalStrength = -1;
 95                } else if (asu <= 0 || asu == 99) {
 96                    voiceSignalStrength = 0;
 97                } else if (asu >= 16) {
 98                    voiceSignalStrength = 4;
 99                } else if (asu >= 8) {
100                    voiceSignalStrength = 3;
101                } else if (asu >= 4) {
102                    voiceSignalStrength = 2;
103                } else {
104                    voiceSignalStrength = 1;
105                }
106            }
107
108            @Override
109            public void onCallStateChanged(int state, String incomingNumber) {
110                callState = state;
111            }
112        },
113                PhoneStateListener.LISTEN_SIGNAL_STRENGTH | PhoneStateListener.LISTEN_SERVICE_STATE
114                        | PhoneStateListener.LISTEN_CALL_STATE);
115
116        descriptionToWidget = new HashMap<String, String>();
117        descriptionToWidget.put(parent.getString(R.string.applications), "APPLAUNCHER");
118        descriptionToWidget.put(parent.getString(R.string.autosync_toggle), "TOGGLE_AUTOSYNC");
119        descriptionToWidget.put(parent.getString(R.string.battery), "BATTERY");
120        descriptionToWidget.put(parent.getString(R.string.bluetooth_toggle), "TOGGLE_BLUETOOTH");
121        descriptionToWidget.put(parent.getString(R.string.location), "LOCATION");
122        descriptionToWidget.put(parent.getString(R.string.search_widget), "VOICE_SEARCH");
123        descriptionToWidget.put(parent.getString(R.string.signal), "CONNECTIVITY");
124        descriptionToWidget.put(parent.getString(R.string.time), "TIME_DATE");
125        descriptionToWidget.put(parent.getString(R.string.voicemail), "VOICEMAIL");
126        descriptionToWidget.put(parent.getString(R.string.wifi_toggle), "TOGGLE_WIFI");
127        descriptionToWidget.put(
128                parent.getString(R.string.open_notifications), "OPEN_NOTIFICATIONS");
129        descriptionToWidget.put(
130                parent.getString(R.string.android_launcher), "ANDROID_LAUNCHER");
131    }
132
133    public void shutdown() {
134        if (guide != null) {
135            guide.shutdown();
136        }
137        try {
138            TelephonyManager tm = (TelephonyManager) parent.getSystemService(
139                    Context.TELEPHONY_SERVICE);
140            tm.listen(new PhoneStateListener() {
141            }, PhoneStateListener.LISTEN_NONE);
142        } catch (RuntimeException e) {
143            // There will be a runtime exception if shutdown is being forced by
144            // the
145            // user.
146            // Ignore the error here as shutdown will be called a second time
147            // when the
148            // shell is destroyed.
149        }
150    }
151
152    /**
153     * Run the widget code corresponding to the given string.
154     */
155    public void runWidget(String widgetName) {
156        if (widgetName.equals("TIME_DATE")) {
157            announceTime();
158        } else if (widgetName.equals("BATTERY")) {
159            announceBattery();
160        } else if (widgetName.equals("VOICEMAIL")) {
161            tts.playEarcon(parent.getString(R.string.earcon_tick), TextToSpeech.QUEUE_FLUSH, null);
162            callVoiceMail();
163        } else if (widgetName.equals("LOCATION")) {
164            tts.playEarcon(parent.getString(R.string.earcon_tick), TextToSpeech.QUEUE_FLUSH, null);
165            speakLocation();
166        } else if (widgetName.equals("CONNECTIVITY")) {
167            announceConnectivity();
168        } else if (widgetName.equals("APPLAUNCHER")) {
169            parent.switchToAppChooserView();
170        } else if (widgetName.equals("VOICE_SEARCH")) {
171            launchVoiceSearch();
172        } else if (widgetName.equals("TOGGLE_BLUETOOTH")) {
173            toggleBluetooth();
174        } else if (widgetName.equals("TOGGLE_AUTOSYNC")) {
175            toggleAutosync();
176        } else if (widgetName.equals("TOGGLE_WIFI")) {
177            toggleWifi();
178        } else if (widgetName.equals("OPEN_NOTIFICATIONS")) {
179            openNotifications();
180        }  else if (widgetName.equals("ANDROID_LAUNCHER")) {
181            launchDefaultHomeScreen();
182        }
183    }
184
185    private void speakDataNetworkInfo() {
186        String info = parent.getString(R.string.no_data_network);
187        ConnectivityManager cManager = (ConnectivityManager) parent.getSystemService(
188                Context.CONNECTIVITY_SERVICE);
189        NetworkInfo networkInfo = cManager.getActiveNetworkInfo();
190        if (networkInfo != null) {
191            if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
192                info = parent.getString(R.string.mobile_data_network);
193                TelephonyManager tm = (TelephonyManager) parent.getSystemService(
194                        Context.TELEPHONY_SERVICE);
195                if (tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS) {
196                    info = parent.getString(R.string.threeg_data_network);
197                } else if (tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_EDGE) {
198                    info = parent.getString(R.string.edge_data_network);
199                }
200            } else if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
201                WifiManager wManager = (WifiManager) parent.getSystemService(Context.WIFI_SERVICE);
202                WifiInfo wInfo = wManager.getConnectionInfo();
203                int wifiSignalStrength = WifiManager.calculateSignalLevel(wInfo.getRssi(), 4);
204                info = parent.getString(R.string.wifi) + wInfo.getSSID() + " "
205                            + parent.getString(R.string.bars, wifiSignalStrength);
206            }
207        }
208        tts.speak(info, TextToSpeech.QUEUE_ADD, null);
209    }
210
211    private void speakVoiceNetworkInfo() {
212        TelephonyManager tm = (TelephonyManager) parent.getSystemService(Context.TELEPHONY_SERVICE);
213        String voiceNetworkOperator = tm.getNetworkOperatorName();
214        String voiceNetworkStrength = parent.getString(R.string.bars, voiceSignalStrength);
215        if (voiceSignalStrength == -1) {
216            voiceNetworkStrength = "";
217        }
218        String voiceNetworkInfo = voiceNetworkOperator + ", " + voiceNetworkStrength;
219        tts.speak(voiceNetworkInfo, TextToSpeech.QUEUE_ADD, null);
220    }
221
222    public void announceConnectivity() {
223        String bluetooth = "";
224        String gps = "";
225        try {
226            ContentResolver cr = parent.getContentResolver();
227            if (System.getInt(cr, System.BLUETOOTH_ON) == 1) {
228                bluetooth = parent.getString(R.string.bluetooth);
229            }
230            String locationProviders = System.getString(cr, System.LOCATION_PROVIDERS_ALLOWED);
231            if ((locationProviders.length() > 0) && locationProviders.contains("gps")) {
232                gps = parent.getString(R.string.gps);
233            }
234
235        } catch (SettingNotFoundException e) {
236            e.printStackTrace();
237        }
238
239        tts.stop();
240        speakVoiceNetworkInfo();
241        speakDataNetworkInfo();
242        tts.speak(bluetooth, TextToSpeech.QUEUE_ADD, null);
243        tts.speak(gps, TextToSpeech.QUEUE_ADD, null);
244    }
245
246    public void announceBattery() {
247        BroadcastReceiver battReceiver = new BroadcastReceiver() {
248            @Override
249            public void onReceive(Context context, Intent intent) {
250                context.unregisterReceiver(this);
251                int rawlevel = intent.getIntExtra("level", -1);
252                int scale = intent.getIntExtra("scale", -1);
253                int status = intent.getIntExtra("status", -1);
254                String message = "";
255                if (rawlevel >= 0 && scale > 0) {
256                    int batteryLevel = (rawlevel * 100) / scale;
257                    message = Integer.toString(batteryLevel) + "%";
258                    // tts.speak(Integer.toString(batteryLevel), 0, null);
259                    // tts.speak("%", 1, null);
260                }
261                if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
262                    // parent.tts.playEarcon(TTSEarcon.SILENCE, 1, null);
263                    // tts.speak(parent.getString(R.string.charging), 1, null);
264                    message = message + " " + parent.getString(R.string.charging);
265                }
266                tts.speak(message, TextToSpeech.QUEUE_FLUSH, null);
267            }
268        };
269        IntentFilter battFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
270        parent.registerReceiver(battReceiver, battFilter);
271    }
272
273    public void announceTime() {
274        Calendar cal = Calendar.getInstance();
275        int day = cal.get(Calendar.DAY_OF_MONTH);
276        SimpleDateFormat monthFormat = new SimpleDateFormat("MMMM");
277        String monthStr = monthFormat.format(cal.getTime());
278        int hour = cal.get(Calendar.HOUR_OF_DAY);
279        int minutes = cal.get(Calendar.MINUTE);
280        String ampm = "";
281        if (hour == 0) {
282            ampm = parent.getString(R.string.midnight);
283            hour = 12;
284        } else if (hour == 12) {
285            ampm = parent.getString(R.string.noon);
286        } else if (hour > 12) {
287            hour = hour - 12;
288            ampm = parent.getString(R.string.pm);
289        } else {
290            ampm = parent.getString(R.string.am);
291        }
292
293        String timeStr = Integer.toString(hour) + " " + Integer.toString(minutes) + " " + ampm;
294
295        tts.speak(timeStr + " " + monthStr + " " + Integer.toString(day), TextToSpeech.QUEUE_FLUSH,
296                null);
297    }
298
299    public void callVoiceMail() {
300        Uri phoneNumberURI = Uri.parse("voicemail:");
301        Intent intent = new Intent(Intent.ACTION_CALL, phoneNumberURI);
302        parent.startActivity(intent);
303    }
304
305    public void speakLocation() {
306        guide = new Guide(parent);
307        guide.speakLocation(useGpsThisTime);
308        useGpsThisTime = !useGpsThisTime;
309    }
310
311    public void launchVoiceSearch() {
312        Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
313        intent.putExtra(
314                RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
315        try {
316            parent.startActivityForResult(intent, MarvinShell.VOICE_RECO_CODE);
317        } catch (ActivityNotFoundException anf) {
318            parent.tts.speak(parent.getString(R.string.search_not_available),
319                    TextToSpeech.QUEUE_FLUSH, null);
320        }
321    }
322
323    public void launchDefaultHomeScreen() {
324        parent.startActivity(parent.getSystemHomeIntent());
325    }
326
327    public int getCallState() {
328        return callState;
329    }
330
331    /**
332     * Toggles the state of the BluetoothAdapter.
333     */
334    public void toggleBluetooth() {
335        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
336        if (adapter.isEnabled()) {
337            if (adapter.disable()) {
338                parent.tts.speak(parent.getString(R.string.bluetooth_turning_off),
339                        TextToSpeech.QUEUE_FLUSH, null);
340            }
341        } else {
342            if (adapter.enable()) {
343                parent.tts.speak(parent.getString(R.string.bluetooth_turning_on),
344                        TextToSpeech.QUEUE_FLUSH, null);
345            }
346        }
347    }
348
349    /**
350     * Toggles the state of the WifiManager.
351     */
352    public void toggleWifi() {
353        WifiManager manager = (WifiManager) parent.getSystemService(Context.WIFI_SERVICE);
354        if (manager.isWifiEnabled()) {
355            if (manager.setWifiEnabled(false)) {
356                parent.tts.speak(
357                        parent.getString(R.string.wifi_off), TextToSpeech.QUEUE_FLUSH, null);
358            }
359        } else {
360            if (manager.setWifiEnabled(true)) {
361                parent.tts.speak(
362                        parent.getString(R.string.wifi_on), TextToSpeech.QUEUE_FLUSH, null);
363            }
364        }
365    }
366
367    /**
368     * Toggles sync settings for apps. that request data in the background.
369     */
370    public void toggleAutosync() {
371        ConnectivityManager manager = (ConnectivityManager) parent.getSystemService(
372                Context.CONNECTIVITY_SERVICE);
373        boolean backgroundData = manager.getBackgroundDataSetting();
374        if (ContentResolver.getMasterSyncAutomatically()) {
375            ContentResolver.setMasterSyncAutomatically(false);
376            parent.tts.speak(
377                    parent.getString(R.string.autosync_off), TextToSpeech.QUEUE_FLUSH, null);
378        } else {
379            ContentResolver.setMasterSyncAutomatically(true);
380            parent.tts.speak(
381                    parent.getString(R.string.autosync_on), TextToSpeech.QUEUE_FLUSH, null);
382            if (!backgroundData) {
383                parent.tts.speak(parent.getString(R.string.background_data_warning),
384                        TextToSpeech.QUEUE_ADD, null);
385            }
386        }
387    }
388
389    /**
390     * Opens the notifications status bar.
391     */
392    public void openNotifications() {
393        try {
394            Object service = parent.getSystemService("statusbar");
395            Class<?> statusBarManager = Class.forName("android.app.StatusBarManager");
396            Method expand = statusBarManager.getMethod("expand");
397            expand.invoke(service);
398        } catch (Exception e) {
399        }
400    }
401}