/TalkBack/src/com/google/android/marvin/talkback/SpeechRuleLoader.java

http://eyes-free.googlecode.com/ · Java · 181 lines · 96 code · 19 blank · 66 comment · 11 complexity · 45efb8a3bb1c5b8adea82690de727899 MD5 · raw file

  1. /*
  2. * Copyright (C) 2010 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of 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,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.google.android.marvin.talkback;
  17. import com.google.android.marvin.talkback.TalkBackService.InfrastructureStateListener;
  18. import android.os.Environment;
  19. import android.os.FileObserver;
  20. import android.util.Log;
  21. import java.io.File;
  22. import java.util.Arrays;
  23. /**
  24. * This class is responsible for loading speech rules.
  25. *
  26. * @author svetoslavganov@google.com (Svetoslav Ganov)
  27. */
  28. class SpeechRuleLoader implements InfrastructureStateListener {
  29. /**
  30. * The {@link SpeechRuleProcessor} that manages speech rules.
  31. */
  32. private final SpeechRuleProcessor mSpeechRuleProcessor;
  33. /**
  34. * The directory that contains external speech strategies.
  35. */
  36. private final File mExternalSpeechStrategyDirectory;
  37. /**
  38. * File observer for grabbing external speech strategies.
  39. */
  40. private final FileObserver mFileObserver;
  41. /**
  42. * Creates a new instance.
  43. *
  44. * @param packageName The TalkBack package name.
  45. * @param speechRuleProcessor The {@link SpeechRuleProcessor} to which to add rules.
  46. * @param deviceIsPhone Flag if the device is a phone.
  47. */
  48. public SpeechRuleLoader(String packageName, SpeechRuleProcessor speechRuleProcessor,
  49. boolean deviceIsPhone) {
  50. mSpeechRuleProcessor = speechRuleProcessor;
  51. mExternalSpeechStrategyDirectory = new File(Environment.getExternalStorageDirectory(),
  52. "/Android/data/" + packageName + "/speechstrategy");
  53. final String speechStrategyDirectory = mExternalSpeechStrategyDirectory.toString();
  54. // Note: FileObserver.MODIFY is fired in both create and modify cases, so
  55. // we register only for FileObserver.MODIFY and FileObserver.DELETE
  56. // to avoid multiple reloads
  57. int flags = FileObserver.DELETE | FileObserver.MODIFY;
  58. mFileObserver = new FileObserver(speechStrategyDirectory, flags) {
  59. @Override
  60. public void onEvent(int event, String speechStrategyRelativePath) {
  61. switch (event) {
  62. case FileObserver.DELETE:
  63. unloadExternalSpeechStrategy(speechStrategyRelativePath);
  64. break;
  65. case FileObserver.MODIFY:
  66. loadExternalSpeechStrategy(speechStrategyRelativePath);
  67. break;
  68. }
  69. }
  70. };
  71. }
  72. /**
  73. * Load all speech rules - internal and external.
  74. */
  75. public void loadSpeechRules() {
  76. // add user defined external speech strategies first or if
  77. // no such create the external speech strategy directory
  78. if (hasExternalSpeechRulesDirectory()) {
  79. loadExternalSpeechStrategies();
  80. } else {
  81. createExternalSpeechRulesDirectory();
  82. }
  83. // add speech strategy for specific built-in Android apps
  84. mSpeechRuleProcessor.addSpeechStrategy(R.raw.speechstrategy_apps);
  85. // add generic speech strategy for views in any app; this should always
  86. // be last so that the app-specific rules above can override the
  87. // generic rules
  88. mSpeechRuleProcessor.addSpeechStrategy(R.raw.speechstrategy);
  89. }
  90. /**
  91. * Creates the external speech rule directory on the SD card if such.
  92. */
  93. private void createExternalSpeechRulesDirectory() {
  94. String state = Environment.getExternalStorageState();
  95. if (Environment.MEDIA_MOUNTED.equals(state)) {
  96. try {
  97. if (mExternalSpeechStrategyDirectory.mkdirs()) {
  98. LogUtils.log(SpeechRuleLoader.class, Log.DEBUG, "Created external speech "
  99. + "rules directory: %s", mExternalSpeechStrategyDirectory);
  100. }
  101. } catch (SecurityException se) {
  102. LogUtils.log(SpeechRuleLoader.class, Log.WARN, "Could not create external "
  103. + "speech rules directory.\n%s", se.toString());
  104. }
  105. } else {
  106. LogUtils.log(SpeechRuleLoader.class, Log.WARN, "Could not create external speech "
  107. + "rules directory: No external storage.");
  108. }
  109. }
  110. /**
  111. * @return True if the external speech rule strategy exists.
  112. */
  113. private boolean hasExternalSpeechRulesDirectory() {
  114. String state = Environment.getExternalStorageState();
  115. if (Environment.MEDIA_MOUNTED.equals(state)
  116. || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
  117. return mExternalSpeechStrategyDirectory.exists();
  118. }
  119. return false;
  120. }
  121. /**
  122. * Loads the external speech rules in alphabetical order.
  123. */
  124. private void loadExternalSpeechStrategies() {
  125. String[] speechStrategyPaths = mExternalSpeechStrategyDirectory.list();
  126. // we load in alphabetical order
  127. Arrays.sort(speechStrategyPaths);
  128. for (String speechStrategyPath : speechStrategyPaths) {
  129. loadExternalSpeechStrategy(speechStrategyPath);
  130. }
  131. }
  132. /**
  133. * Loads an external speech strategy with the given
  134. * <code>speechStrategyPath</code>.
  135. */
  136. private void loadExternalSpeechStrategy(String speechStrategyRelativePath) {
  137. File speechStrategyFile = new File(mExternalSpeechStrategyDirectory,
  138. speechStrategyRelativePath);
  139. mSpeechRuleProcessor.addSpeechStrategy(speechStrategyFile);
  140. LogUtils.log(SpeechRuleLoader.class, Log.INFO, "Loaded external speech strategy: %s",
  141. speechStrategyRelativePath);
  142. }
  143. /**
  144. * Unloads an external speech strategy with the given
  145. * <code>speechStrategyPath</code>.
  146. */
  147. private void unloadExternalSpeechStrategy(String speechStrategyRelativePath) {
  148. File speechStrategyFile = new File(mExternalSpeechStrategyDirectory,
  149. speechStrategyRelativePath);
  150. mSpeechRuleProcessor.removeSpeechStrategy(speechStrategyFile);
  151. LogUtils.log(SpeechRuleLoader.class, Log.INFO, "Removed external speech strategy: %s",
  152. speechStrategyRelativePath);
  153. }
  154. @Override
  155. public void onInfrastructureStateChange(boolean isInitialized) {
  156. if (isInitialized) {
  157. mFileObserver.startWatching();
  158. } else {
  159. mFileObserver.stopWatching();
  160. }
  161. }
  162. }