/ocr/ocrservice/src/com/googlecode/eyesfree/ocr/service/OcrService.java

http://eyes-free.googlecode.com/ · Java · 318 lines · 209 code · 58 blank · 51 comment · 30 complexity · 1cfed3a196b3771ff3b574562303f97a MD5 · raw file

  1. /*
  2. * Copyright (C) 2011 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. package com.googlecode.eyesfree.ocr.service;
  17. import android.app.Service;
  18. import android.content.BroadcastReceiver;
  19. import android.content.Context;
  20. import android.content.Intent;
  21. import android.content.IntentFilter;
  22. import android.content.pm.PackageInfo;
  23. import android.content.pm.PackageManager;
  24. import android.content.pm.PackageManager.NameNotFoundException;
  25. import android.os.IBinder;
  26. import android.os.RemoteCallbackList;
  27. import android.os.RemoteException;
  28. import android.util.Log;
  29. import com.googlecode.eyesfree.ocr.client.IOcr;
  30. import com.googlecode.eyesfree.ocr.client.IOcrCallback;
  31. import com.googlecode.eyesfree.ocr.client.Intents;
  32. import com.googlecode.eyesfree.ocr.client.Language;
  33. import com.googlecode.eyesfree.ocr.client.Ocr;
  34. import com.googlecode.eyesfree.ocr.client.OcrResult;
  35. import com.googlecode.eyesfree.ocr.client.Ocr.Parameters;
  36. import com.googlecode.eyesfree.ocr.service.OcrTaskProcessor.OcrTaskListener;
  37. import java.io.File;
  38. import java.util.ArrayList;
  39. import java.util.HashMap;
  40. import java.util.List;
  41. /**
  42. * Provides services for recognizing text in images. Specifically handles
  43. * binding the service to clients.
  44. *
  45. * @author alanv@google.com (Alan Viverette)
  46. */
  47. public class OcrService extends Service {
  48. private static final String TAG = "OcrService";
  49. private final OcrService mSelf = this;
  50. private RemoteCallbackList<IOcrCallback> mCallbacks;
  51. private HashMap<Integer, IOcrCallback> mCallbacksMap;
  52. private LanguageManager mLanguageManager;
  53. private OcrTaskProcessor mOcrTaskProcessor;
  54. @Override
  55. public void onCreate() {
  56. super.onCreate();
  57. Log.i(TAG, "Service starting...");
  58. mCallbacks = new RemoteCallbackList<IOcrCallback>();
  59. mCallbacksMap = new HashMap<Integer, IOcrCallback>();
  60. mLanguageManager = new LanguageManager(this);
  61. mLanguageManager.loadLanguages();
  62. mOcrTaskProcessor = new OcrTaskProcessor(mLanguageManager.getDatapath());
  63. mOcrTaskProcessor.setListener(mOcrTaskListener);
  64. IntentFilter filter = new IntentFilter();
  65. filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
  66. filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
  67. filter.addAction(Intent.ACTION_MEDIA_EJECT);
  68. filter.addDataScheme("file");
  69. registerReceiver(mBroadcastReceiver, filter);
  70. }
  71. @Override
  72. public void onDestroy() {
  73. Log.i(TAG, "Service is shutting down...");
  74. unregisterReceiver(mBroadcastReceiver);
  75. mCallbacks.kill();
  76. super.onDestroy();
  77. }
  78. private void applyDefaults(Ocr.Parameters params) {
  79. // TODO(alanv): Make sure language choice is valid
  80. /*
  81. * boolean override = mPrefs.getBoolean("override_pref", false); if
  82. * (override || config.language == null) { config.language =
  83. * mPrefs.getString("lang_pref", "eng"); } if (override ||
  84. * !config.variables.containsKey(Config.VAR_ACCURACYVSPEED)) {
  85. * config.variables.put(Config.VAR_ACCURACYVSPEED,
  86. * mPrefs.getString("speed_pref", "0")); } if (override ||
  87. * !config.debug) { config.debug = mPrefs.getBoolean("debug_pref",
  88. * false); }
  89. */
  90. }
  91. @Override
  92. public IBinder onBind(Intent intent) {
  93. if (Intents.Service.ACTION.equals(intent.getAction())) {
  94. for (String category : intent.getCategories()) {
  95. if (Intents.Service.CATEGORY.equals(category)) {
  96. return mBinder;
  97. }
  98. }
  99. }
  100. return null;
  101. }
  102. /**
  103. * Attempts to cancel the OCR processor job with the specified token
  104. * belonging to the specified process ID.
  105. *
  106. * @param pid
  107. * @param token
  108. */
  109. private boolean cancel(int pid, long token) {
  110. return mOcrTaskProcessor.cancel(pid, token);
  111. }
  112. /**
  113. * Attempts to cancel all OCR processor jobs belonging to the specified
  114. * process ID.
  115. *
  116. * @param pid
  117. */
  118. private boolean stop(int pid) {
  119. return mOcrTaskProcessor.cancelAll(pid);
  120. }
  121. /**
  122. * Returns the version number of the OCR package. This version number is the
  123. * versionCode from the AndroidManifest.xml
  124. *
  125. * @return The version number of the OCR package
  126. */
  127. private int getVersion() {
  128. PackageManager manager = mSelf.getPackageManager();
  129. PackageInfo info = new PackageInfo();
  130. try {
  131. info = manager.getPackageInfo(mSelf.getPackageName(), 0);
  132. } catch (NameNotFoundException e) {
  133. e.printStackTrace();
  134. return -1;
  135. }
  136. return info.versionCode;
  137. }
  138. private long enqueueData(int pid, byte[] data, Parameters params) {
  139. if (data == null || data.length == 0) {
  140. Log.e(TAG, "Attempted to enqueue null or empty data");
  141. return Ocr.INVALID_TOKEN;
  142. }
  143. if (params == null) {
  144. Log.e(TAG, "Attempted to enqueue null params");
  145. return Ocr.INVALID_TOKEN;
  146. }
  147. applyDefaults(params);
  148. return mOcrTaskProcessor.enqueueData(pid, data, params);
  149. }
  150. private long enqueueFile(int pid, String filename, Parameters params) {
  151. if (filename == null) {
  152. Log.e(TAG, "Attempted to enqueue null filename");
  153. return Ocr.INVALID_TOKEN;
  154. }
  155. if (params == null) {
  156. Log.e(TAG, "Attempted to enqueue null params");
  157. return Ocr.INVALID_TOKEN;
  158. }
  159. final File file = new File(filename);
  160. if (!file.exists() || !file.canRead()) {
  161. Log.e(TAG, "Attempted to enqueue unreadable file");
  162. return Ocr.INVALID_TOKEN;
  163. }
  164. applyDefaults(params);
  165. return mOcrTaskProcessor.enqueueFile(pid, file, params);
  166. }
  167. private void setCallback(int pid, IOcrCallback callback) {
  168. if (callback != null) {
  169. mCallbacks.register(callback);
  170. mCallbacksMap.put(pid, callback);
  171. } else {
  172. callback = mCallbacksMap.get(pid);
  173. if (callback != null) {
  174. mCallbacks.unregister(callback);
  175. }
  176. }
  177. }
  178. private final IOcr.Stub mBinder = new IOcr.Stub() {
  179. @Override
  180. public void setCallback(IOcrCallback cb) {
  181. mSelf.setCallback(getCallingPid(), cb);
  182. }
  183. @Override
  184. public long enqueueData(byte[] data, Parameters params) {
  185. return mSelf.enqueueData(getCallingPid(), data, params);
  186. }
  187. @Override
  188. public long enqueueFile(String filename, Parameters params) {
  189. return mSelf.enqueueFile(getCallingPid(), filename, params);
  190. }
  191. @Override
  192. public boolean cancel(long token) {
  193. return mSelf.cancel(getCallingPid(), token);
  194. }
  195. @Override
  196. public boolean stop() {
  197. return mSelf.stop(getCallingPid());
  198. }
  199. @Override
  200. public int getVersion() {
  201. return mSelf.getVersion();
  202. }
  203. @Override
  204. public boolean reloadLanguages() {
  205. return mLanguageManager.loadLanguages();
  206. }
  207. @Override
  208. public List<Language> getAvailableLanguages() {
  209. return mLanguageManager.getAvailable();
  210. }
  211. @Override
  212. public String getDatapath() {
  213. File datapath = mLanguageManager.getDatapath();
  214. return datapath == null ? null : datapath.getAbsolutePath();
  215. }
  216. @Override
  217. public String getTessdata() {
  218. File tessdata = mLanguageManager.getTessdata();
  219. return tessdata == null ? null : tessdata.getAbsolutePath();
  220. }
  221. };
  222. private final OcrTaskListener mOcrTaskListener = new OcrTaskListener() {
  223. @Override
  224. public void onResult(int pid, long token, OcrResult result) {
  225. final IOcrCallback callback = mCallbacksMap.get(pid);
  226. if (callback == null) {
  227. return;
  228. }
  229. try {
  230. callback.onResult(token, result);
  231. } catch (RemoteException e) {
  232. e.printStackTrace();
  233. }
  234. }
  235. @Override
  236. public void onCompleted(int pid, long token, ArrayList<OcrResult> results) {
  237. IOcrCallback callback = mCallbacksMap.get(pid);
  238. if (callback == null) {
  239. return;
  240. }
  241. try {
  242. callback.onCompleted(token, results);
  243. } catch (RemoteException e) {
  244. e.printStackTrace();
  245. }
  246. }
  247. };
  248. private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
  249. @Override
  250. public void onReceive(Context context, Intent intent) {
  251. if (Intent.ACTION_MEDIA_MOUNTED.equals(intent.getAction())
  252. || Intent.ACTION_MEDIA_UNMOUNTED.equals(intent.getAction())) {
  253. mLanguageManager.loadLanguages();
  254. } else if (Intent.ACTION_MEDIA_EJECT.equals(intent.getAction())) {
  255. mOcrTaskProcessor.abort();
  256. Log.i(TAG, "Preparing for media eject");
  257. }
  258. }
  259. };
  260. }