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