Modify the base gestures API to use streams instead of files. Adds new wrappers to easily load/save gestures from files, resources, etc. Do the same for the letters recognizer.
diff --git a/core/java/android/gesture/GestureLibrary.java b/core/java/android/gesture/GestureLibrary.java
index 9020d2b..a29c2c8 100644
--- a/core/java/android/gesture/GestureLibrary.java
+++ b/core/java/android/gesture/GestureLibrary.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009 The Android Open Source Project
+ * Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,337 +14,68 @@
* limitations under the License.
*/
+
package android.gesture;
-import android.util.Log;
-import android.os.SystemClock;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.DataOutputStream;
-import java.io.DataInputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.Set;
-import java.util.Map;
+import java.util.ArrayList;
-import static android.gesture.GestureConstants.LOG_TAG;
+public abstract class GestureLibrary {
+ protected final GestureStore mStore;
-/**
- * GestureLibrary maintains gesture examples and makes predictions on a new
- * gesture
- */
-//
-// File format for GestureLibrary:
-//
-// Nb. bytes Java type Description
-// -----------------------------------
-// Header
-// 2 bytes short File format version number
-// 4 bytes int Number of entries
-// Entry
-// X bytes UTF String Entry name
-// 4 bytes int Number of gestures
-// Gesture
-// 8 bytes long Gesture ID
-// 4 bytes int Number of strokes
-// Stroke
-// 4 bytes int Number of points
-// Point
-// 4 bytes float X coordinate of the point
-// 4 bytes float Y coordinate of the point
-// 8 bytes long Time stamp
-//
-public class GestureLibrary {
- public static final int SEQUENCE_INVARIANT = 1;
- // when SEQUENCE_SENSITIVE is used, only single stroke gestures are currently allowed
- public static final int SEQUENCE_SENSITIVE = 2;
-
- // ORIENTATION_SENSITIVE and ORIENTATION_INVARIANT are only for SEQUENCE_SENSITIVE gestures
- public static final int ORIENTATION_INVARIANT = 1;
- public static final int ORIENTATION_SENSITIVE = 2;
-
- private static final short FILE_FORMAT_VERSION = 1;
-
- private static final boolean PROFILE_LOADING_SAVING = false;
-
- private int mSequenceType = SEQUENCE_SENSITIVE;
- private int mOrientationStyle = ORIENTATION_SENSITIVE;
-
- private final String mGestureFileName;
-
- private final HashMap<String, ArrayList<Gesture>> mNamedGestures =
- new HashMap<String, ArrayList<Gesture>>();
-
- private Learner mClassifier;
-
- private boolean mChanged = false;
-
- /**
- * @param path where gesture data is stored
- */
- public GestureLibrary(String path) {
- mGestureFileName = path;
- mClassifier = new InstanceLearner();
+ protected GestureLibrary() {
+ mStore = new GestureStore();
}
- /**
- * Specify how the gesture library will handle orientation.
- * Use ORIENTATION_INVARIANT or ORIENTATION_SENSITIVE
- *
- * @param style
- */
+ public abstract boolean save();
+
+ public abstract boolean load();
+
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ public Learner getLearner() {
+ return mStore.getLearner();
+ }
+
public void setOrientationStyle(int style) {
- mOrientationStyle = style;
+ mStore.setOrientationStyle(style);
}
public int getOrientationStyle() {
- return mOrientationStyle;
+ return mStore.getOrientationStyle();
}
- /**
- * @param type SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE
- */
public void setSequenceType(int type) {
- mSequenceType = type;
+ mStore.setSequenceType(type);
}
- /**
- * @return SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE
- */
public int getSequenceType() {
- return mSequenceType;
+ return mStore.getSequenceType();
}
- /**
- * Get all the gesture entry names in the library
- *
- * @return a set of strings
- */
public Set<String> getGestureEntries() {
- return mNamedGestures.keySet();
+ return mStore.getGestureEntries();
}
- /**
- * Recognize a gesture
- *
- * @param gesture the query
- * @return a list of predictions of possible entries for a given gesture
- */
public ArrayList<Prediction> recognize(Gesture gesture) {
- Instance instance = Instance.createInstance(mSequenceType, mOrientationStyle, gesture, null);
- return mClassifier.classify(mSequenceType, instance.vector);
+ return mStore.recognize(gesture);
}
- /**
- * Add a gesture for the entry
- *
- * @param entryName entry name
- * @param gesture
- */
public void addGesture(String entryName, Gesture gesture) {
- if (entryName == null || entryName.length() == 0) {
- return;
- }
- ArrayList<Gesture> gestures = mNamedGestures.get(entryName);
- if (gestures == null) {
- gestures = new ArrayList<Gesture>();
- mNamedGestures.put(entryName, gestures);
- }
- gestures.add(gesture);
- mClassifier.addInstance(Instance.createInstance(mSequenceType, mOrientationStyle, gesture, entryName));
- mChanged = true;
+ mStore.addGesture(entryName, gesture);
}
- /**
- * Remove a gesture from the library. If there are no more gestures for the
- * given entry, the gesture entry will be removed.
- *
- * @param entryName entry name
- * @param gesture
- */
public void removeGesture(String entryName, Gesture gesture) {
- ArrayList<Gesture> gestures = mNamedGestures.get(entryName);
- if (gestures == null) {
- return;
- }
-
- gestures.remove(gesture);
-
- // if there are no more samples, remove the entry automatically
- if (gestures.isEmpty()) {
- mNamedGestures.remove(entryName);
- }
-
- mClassifier.removeInstance(gesture.getID());
-
- mChanged = true;
+ mStore.removeGesture(entryName, gesture);
}
- /**
- * Remove a entry of gestures
- *
- * @param entryName the entry name
- */
public void removeEntry(String entryName) {
- mNamedGestures.remove(entryName);
- mClassifier.removeInstances(entryName);
- mChanged = true;
+ mStore.removeEntry(entryName);
}
- /**
- * Get all the gestures of an entry
- *
- * @param entryName
- * @return the list of gestures that is under this name
- */
public ArrayList<Gesture> getGestures(String entryName) {
- ArrayList<Gesture> gestures = mNamedGestures.get(entryName);
- if (gestures != null) {
- return new ArrayList<Gesture>(gestures);
- } else {
- return null;
- }
- }
-
- /**
- * Save the gesture library
- */
- public boolean save() {
- if (!mChanged) {
- return true;
- }
-
- boolean result = false;
- DataOutputStream out = null;
-
- try {
- File file = new File(mGestureFileName);
- if (!file.getParentFile().exists()) {
- if (!file.getParentFile().mkdirs()) {
- return false;
- }
- }
-
- long start;
- if (PROFILE_LOADING_SAVING) {
- start = SystemClock.elapsedRealtime();
- }
-
- final HashMap<String, ArrayList<Gesture>> maps = mNamedGestures;
-
- out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file),
- GestureConstants.IO_BUFFER_SIZE));
- // Write version number
- out.writeShort(FILE_FORMAT_VERSION);
- // Write number of entries
- out.writeInt(maps.size());
-
- for (Map.Entry<String, ArrayList<Gesture>> entry : maps.entrySet()) {
- final String key = entry.getKey();
- final ArrayList<Gesture> examples = entry.getValue();
- final int count = examples.size();
-
- // Write entry name
- out.writeUTF(key);
- // Write number of examples for this entry
- out.writeInt(count);
-
- for (int i = 0; i < count; i++) {
- examples.get(i).serialize(out);
- }
- }
-
- out.flush();
-
- if (PROFILE_LOADING_SAVING) {
- long end = SystemClock.elapsedRealtime();
- Log.d(LOG_TAG, "Saving gestures library = " + (end - start) + " ms");
- }
-
- mChanged = false;
- result = true;
- } catch (IOException ex) {
- Log.d(LOG_TAG, "Failed to save gestures:", ex);
- } finally {
- GestureUtilities.closeStream(out);
- }
-
- return result;
- }
-
- /**
- * Load the gesture library
- */
- public boolean load() {
- boolean result = false;
-
- final File file = new File(mGestureFileName);
- if (file.exists()) {
- DataInputStream in = null;
- try {
- in = new DataInputStream(new BufferedInputStream(
- new FileInputStream(mGestureFileName), GestureConstants.IO_BUFFER_SIZE));
-
- long start;
- if (PROFILE_LOADING_SAVING) {
- start = SystemClock.elapsedRealtime();
- }
-
- // Read file format version number
- final short versionNumber = in.readShort();
- switch (versionNumber) {
- case 1:
- readFormatV1(in);
- break;
- }
-
- if (PROFILE_LOADING_SAVING) {
- long end = SystemClock.elapsedRealtime();
- Log.d(LOG_TAG, "Loading gestures library = " + (end - start) + " ms");
- }
-
- result = true;
- } catch (IOException ex) {
- Log.d(LOG_TAG, "Failed to load gestures:", ex);
- } finally {
- GestureUtilities.closeStream(in);
- }
- }
-
- return result;
- }
-
- private void readFormatV1(DataInputStream in) throws IOException {
- final Learner classifier = mClassifier;
- final HashMap<String, ArrayList<Gesture>> namedGestures = mNamedGestures;
- namedGestures.clear();
-
- // Number of entries in the library
- final int entriesCount = in.readInt();
-
- for (int i = 0; i < entriesCount; i++) {
- // Entry name
- final String name = in.readUTF();
- // Number of gestures
- final int gestureCount = in.readInt();
-
- final ArrayList<Gesture> gestures = new ArrayList<Gesture>(gestureCount);
- for (int j = 0; j < gestureCount; j++) {
- final Gesture gesture = Gesture.deserialize(in);
- gestures.add(gesture);
- classifier.addInstance(Instance.createInstance(mSequenceType, mOrientationStyle, gesture, name));
- }
-
- namedGestures.put(name, gestures);
- }
- }
-
- Learner getLearner() {
- return mClassifier;
+ return mStore.getGestures(entryName);
}
}