/shell/src/com/google/marvin/shell/AuditoryWidgets.java
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}