merge master to master_gl

This commit is contained in:
Mathias Agopian
2009-05-31 01:16:45 -07:00
108 changed files with 5885 additions and 2403 deletions

View File

@@ -74,10 +74,12 @@ public class PackageParser {
* added to older SDKs appearing before those added to newer SDKs.
* @hide
*/
public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] = new PackageParser.NewPermissionInfo[] {
new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_SDCARD,
android.os.Build.VERSION_CODES.DONUT,
0)
public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
new PackageParser.NewPermissionInfo[] {
new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_SDCARD,
android.os.Build.VERSION_CODES.DONUT, 0),
new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
android.os.Build.VERSION_CODES.DONUT, 0)
};
private String mArchiveSourcePath;

View File

@@ -46,7 +46,7 @@ public class Gesture implements Parcelable {
private static int sGestureCount = 0;
private RectF mBoundingBox;
private final RectF mBoundingBox = new RectF();
// the same as its instance ID
private long mGestureID;
@@ -83,12 +83,7 @@ public class Gesture implements Parcelable {
*/
public void addStroke(GestureStroke stroke) {
mStrokes.add(stroke);
if (mBoundingBox == null) {
mBoundingBox = new RectF(stroke.boundingBox);
} else {
mBoundingBox.union(stroke.boundingBox);
}
mBoundingBox.union(stroke.boundingBox);
}
/**

View File

@@ -0,0 +1,139 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.gesture;
import android.util.Log;
import static android.gesture.GestureConstants.*;
import android.content.Context;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.ref.WeakReference;
public final class GestureLibraries {
private GestureLibraries() {
}
public static GestureLibrary fromFile(String path) {
return fromFile(new File(path));
}
public static GestureLibrary fromFile(File path) {
return new FileGestureLibrary(path);
}
public static GestureLibrary fromPrivateFile(Context context, String name) {
return fromFile(context.getFileStreamPath(name));
}
public static GestureLibrary fromRawResource(Context context, int resourceId) {
return new ResourceGestureLibrary(context, resourceId);
}
private static class FileGestureLibrary extends GestureLibrary {
private final File mPath;
public FileGestureLibrary(File path) {
mPath = path;
}
@Override
public boolean isReadOnly() {
return !mPath.canWrite();
}
public boolean save() {
final File file = mPath;
if (!file.canWrite()) return false;
if (!file.getParentFile().exists()) {
if (!file.getParentFile().mkdirs()) {
return false;
}
}
boolean result = false;
try {
mStore.save(new FileOutputStream(file), true);
result = true;
} catch (FileNotFoundException e) {
Log.d(LOG_TAG, "Could not save the gesture library in " + mPath, e);
} catch (IOException e) {
Log.d(LOG_TAG, "Could not save the gesture library in " + mPath, e);
}
return result;
}
public boolean load() {
boolean result = false;
final File file = mPath;
if (file.exists() && file.canRead()) {
try {
mStore.load(new FileInputStream(file), true);
result = true;
} catch (FileNotFoundException e) {
Log.d(LOG_TAG, "Could not load the gesture library from " + mPath, e);
} catch (IOException e) {
Log.d(LOG_TAG, "Could not load the gesture library from " + mPath, e);
}
}
return result;
}
}
private static class ResourceGestureLibrary extends GestureLibrary {
private final WeakReference<Context> mContext;
private final int mResourceId;
public ResourceGestureLibrary(Context context, int resourceId) {
mContext = new WeakReference<Context>(context);
mResourceId = resourceId;
}
@Override
public boolean isReadOnly() {
return true;
}
public boolean save() {
return false;
}
public boolean load() {
boolean result = false;
final Context context = mContext.get();
if (context != null) {
final InputStream in = context.getResources().openRawResource(mResourceId);
try {
mStore.load(in, true);
result = true;
} catch (IOException e) {
Log.d(LOG_TAG, "Could not load the gesture library from raw resource " +
context.getResources().getResourceName(mResourceId), e);
}
}
return result;
}
}
}

View File

@@ -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,333 +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();
}
public abstract boolean save();
public abstract boolean load();
public boolean isReadOnly() {
return false;
}
public Learner getLearner() {
return mStore.getLearner();
}
/**
* Specify how the gesture library will handle orientation.
* Use ORIENTATION_INVARIANT or ORIENTATION_SENSITIVE
*
* @param style
*/
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, 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, 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, gesture, name));
}
namedGestures.put(name, gestures);
}
return mStore.getGestures(entryName);
}
}

View File

@@ -45,8 +45,9 @@ import java.util.ArrayList;
* @attr ref android.R.styleable#GestureOverlayView_gestureStrokeAngleThreshold
* @attr ref android.R.styleable#GestureOverlayView_gestureStrokeLengthThreshold
* @attr ref android.R.styleable#GestureOverlayView_gestureStrokeSquarenessThreshold
* @attr ref android.R.styleable#GestureOverlayView_gestureStrokeType
* @attr ref android.R.styleable#GestureOverlayView_gestureStrokeType
* @attr ref android.R.styleable#GestureOverlayView_gestureColor
* @attr ref android.R.styleable#GestureOverlayView_orientation
* @attr ref android.R.styleable#GestureOverlayView_uncertainGestureColor
*/
public class GestureOverlayView extends FrameLayout {
@@ -75,7 +76,7 @@ public class GestureOverlayView extends FrameLayout {
private int mInvalidateExtraBorder = 10;
private int mGestureStrokeType = GESTURE_STROKE_TYPE_SINGLE;
private float mGestureStrokeLengthThreshold = 30.0f;
private float mGestureStrokeLengthThreshold = 50.0f;
private float mGestureStrokeSquarenessTreshold = 0.275f;
private float mGestureStrokeAngleThreshold = 40.0f;
@@ -86,7 +87,7 @@ public class GestureOverlayView extends FrameLayout {
private float mX;
private float mY;
private float mCurveEndX;
private float mCurveEndY;
@@ -516,12 +517,12 @@ public class GestureOverlayView extends FrameLayout {
final int count = listeners.size();
for (int i = 0; i < count; i++) {
listeners.get(i).onGestureStarted(this, event);
}
}
}
private Rect touchMove(MotionEvent event) {
Rect areaToRefresh = null;
final float x = event.getX();
final float y = event.getY();
@@ -530,7 +531,7 @@ public class GestureOverlayView extends FrameLayout {
final float dx = Math.abs(x - previousX);
final float dy = Math.abs(y - previousY);
if (dx >= GestureStroke.TOUCH_TOLERANCE || dy >= GestureStroke.TOUCH_TOLERANCE) {
areaToRefresh = mInvalidRect;
@@ -538,55 +539,55 @@ public class GestureOverlayView extends FrameLayout {
final int border = mInvalidateExtraBorder;
areaToRefresh.set((int) mCurveEndX - border, (int) mCurveEndY - border,
(int) mCurveEndX + border, (int) mCurveEndY + border);
float cX = mCurveEndX = (x + previousX) / 2;
float cY = mCurveEndY = (y + previousY) / 2;
mPath.quadTo(previousX, previousY, cX, cY);
// union with the control point of the new curve
areaToRefresh.union((int) previousX - border, (int) previousY - border,
(int) previousX + border, (int) previousY + border);
// union with the end point of the new curve
areaToRefresh.union((int) cX - border, (int) cY - border,
(int) cX + border, (int) cY + border);
mX = x;
mY = y;
}
mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
if (mHandleGestureActions && !mIsGesturing) {
mTotalLength += (float) Math.sqrt(dx * dx + dy * dy);
if (mHandleGestureActions && !mIsGesturing) {
mTotalLength += (float) Math.sqrt(dx * dx + dy * dy);
if (mTotalLength > mGestureStrokeLengthThreshold) {
final OrientedBoundingBox box =
GestureUtilities.computeOrientedBoundingBox(mStrokeBuffer);
if (mTotalLength > mGestureStrokeLengthThreshold) {
final OrientedBoundingBox box =
GestureUtilities.computeOrientedBoundingBox(mStrokeBuffer);
float angle = Math.abs(box.orientation);
if (angle > 90) {
angle = 180 - angle;
}
float angle = Math.abs(box.orientation);
if (angle > 90) {
angle = 180 - angle;
}
if (box.squareness > mGestureStrokeSquarenessTreshold ||
(mOrientation == ORIENTATION_VERTICAL ?
angle < mGestureStrokeAngleThreshold :
angle > mGestureStrokeAngleThreshold)) {
if (box.squareness > mGestureStrokeSquarenessTreshold ||
(mOrientation == ORIENTATION_VERTICAL ?
angle < mGestureStrokeAngleThreshold :
angle > mGestureStrokeAngleThreshold)) {
mIsGesturing = true;
setCurrentColor(mCertainGestureColor);
mIsGesturing = true;
setCurrentColor(mCertainGestureColor);
}
}
}
}
// pass the event to handlers
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
final int count = listeners.size();
for (int i = 0; i < count; i++) {
listeners.get(i).onGesture(this, event);
}
// pass the event to handlers
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
final int count = listeners.size();
for (int i = 0; i < count; i++) {
listeners.get(i).onGesture(this, event);
}
}
return areaToRefresh;
}
@@ -594,35 +595,45 @@ public class GestureOverlayView extends FrameLayout {
private void touchUp(MotionEvent event, boolean cancel) {
mIsListeningForGestures = false;
// add the stroke to the current gesture
mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer));
mStrokeBuffer.clear();
// A gesture wasn't started or was cancelled
if (mCurrentGesture != null) {
// add the stroke to the current gesture
mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer));
if (!cancel) {
// pass the event to handlers
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
int count = listeners.size();
for (int i = 0; i < count; i++) {
listeners.get(i).onGestureEnded(this, event);
}
if (!cancel) {
// pass the event to handlers
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
int count = listeners.size();
for (int i = 0; i < count; i++) {
listeners.get(i).onGestureEnded(this, event);
}
if (mHandleGestureActions) {
clear(mFadeEnabled, mIsGesturing);
}
} else {
cancelGesture(event);
if (mHandleGestureActions) {
clear(mFadeEnabled, mIsGesturing);
}
} else {
// pass the event to handlers
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
final int count = listeners.size();
for (int i = 0; i < count; i++) {
listeners.get(i).onGestureCancelled(this, event);
}
clear(false);
cancelGesture(event);
}
mStrokeBuffer.clear();
mIsGesturing = false;
}
private void cancelGesture(MotionEvent event) {
// pass the event to handlers
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
final int count = listeners.size();
for (int i = 0; i < count; i++) {
listeners.get(i).onGestureCancelled(this, event);
}
clear(false);
}
private void fireOnGesturePerformed() {
final ArrayList<OnGesturePerformedListener> actionListeners =
mOnGesturePerformedListeners;
@@ -668,7 +679,7 @@ public class GestureOverlayView extends FrameLayout {
setPaintAlpha(255);
}
invalidate();
invalidate();
}
}

View File

@@ -0,0 +1,330 @@
/*
* Copyright (C) 2008-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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* 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.IOException;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import java.util.Map;
import static android.gesture.GestureConstants.LOG_TAG;
/**
* GestureLibrary maintains gesture examples and makes predictions on a new
* gesture
*/
//
// File format for GestureStore:
//
// 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 GestureStore {
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 HashMap<String, ArrayList<Gesture>> mNamedGestures =
new HashMap<String, ArrayList<Gesture>>();
private Learner mClassifier;
private boolean mChanged = false;
public GestureStore() {
mClassifier = new InstanceLearner();
}
/**
* Specify how the gesture library will handle orientation.
* Use ORIENTATION_INVARIANT or ORIENTATION_SENSITIVE
*
* @param style
*/
public void setOrientationStyle(int style) {
mOrientationStyle = style;
}
public int getOrientationStyle() {
return mOrientationStyle;
}
/**
* @param type SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE
*/
public void setSequenceType(int type) {
mSequenceType = type;
}
/**
* @return SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE
*/
public int getSequenceType() {
return mSequenceType;
}
/**
* Get all the gesture entry names in the library
*
* @return a set of strings
*/
public Set<String> getGestureEntries() {
return mNamedGestures.keySet();
}
/**
* 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);
}
/**
* 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;
}
/**
* 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;
}
/**
* Remove a entry of gestures
*
* @param entryName the entry name
*/
public void removeEntry(String entryName) {
mNamedGestures.remove(entryName);
mClassifier.removeInstances(entryName);
mChanged = true;
}
/**
* 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 void save(OutputStream stream) throws IOException {
save(stream, false);
}
public void save(OutputStream stream, boolean closeStream) throws IOException {
if (!mChanged) {
return;
}
DataOutputStream out = null;
try {
long start;
if (PROFILE_LOADING_SAVING) {
start = SystemClock.elapsedRealtime();
}
final HashMap<String, ArrayList<Gesture>> maps = mNamedGestures;
out = new DataOutputStream((stream instanceof BufferedOutputStream) ? out :
new BufferedOutputStream(out, 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;
} finally {
if (closeStream) GestureUtilities.closeStream(out);
}
}
/**
* Load the gesture library
*/
public void load(InputStream stream) throws IOException {
load(stream, false);
}
public void load(InputStream stream, boolean closeStream) throws IOException {
DataInputStream in = null;
try {
in = new DataInputStream((stream instanceof BufferedInputStream) ? stream :
new BufferedInputStream(stream, 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");
}
} finally {
if (closeStream) GestureUtilities.closeStream(in);
}
}
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;
}
}

View File

@@ -17,7 +17,6 @@
package android.gesture;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
@@ -31,7 +30,7 @@ import java.util.ArrayList;
* A gesture stroke started on a touch down and ended on a touch up.
*/
public class GestureStroke {
static final float TOUCH_TOLERANCE = 3;
static final float TOUCH_TOLERANCE = 8;
public final RectF boundingBox;
@@ -147,10 +146,12 @@ public class GestureStroke {
final float[] pts = GestureUtilities.temporalSampling(this, numSample);
final RectF rect = boundingBox;
final Matrix matrix = new Matrix();
matrix.setTranslate(-rect.left, -rect.top);
matrix.postScale(width / rect.width(), height / rect.height());
matrix.mapPoints(pts);
GestureUtilities.translate(pts, -rect.left, -rect.top);
float sx = width / rect.width();
float sy = height / rect.height();
float scale = sx > sy ? sy : sx;
GestureUtilities.scale(pts, scale, scale);
float mX = 0;
float mY = 0;

View File

@@ -17,7 +17,6 @@
package android.gesture;
import android.graphics.RectF;
import android.graphics.Matrix;
import android.util.Log;
import java.util.ArrayList;
@@ -380,22 +379,17 @@ final class GestureUtilities {
}
static OrientedBoundingBox computeOrientedBoundingBox(float[] points, float[] centroid) {
Matrix tr = new Matrix();
tr.setTranslate(-centroid[0], -centroid[1]);
tr.mapPoints(points);
translate(points, -centroid[0], -centroid[1]);
double[][] array = computeCoVariance(points);
double[] targetVector = computeOrientation(array);
float angle;
if (targetVector[0] == 0 && targetVector[1] == 0) {
angle = -90;
angle = (float) -Math.PI/2;
} else { // -PI<alpha<PI
angle = (float) Math.atan2(targetVector[1], targetVector[0]);
angle = (float) (180 * angle / Math.PI);
Matrix trans = new Matrix();
trans.setRotate(-angle);
trans.mapPoints(points);
rotate(points, -angle);
}
float minx = Float.MAX_VALUE;
@@ -419,7 +413,7 @@ final class GestureUtilities {
}
}
return new OrientedBoundingBox(angle, centroid[0], centroid[1], maxx - minx, maxy - miny);
return new OrientedBoundingBox((float) (angle * 180 / Math.PI), centroid[0], centroid[1], maxx - minx, maxy - miny);
}
private static double[] computeOrientation(double[][] covarianceMatrix) {
@@ -446,4 +440,36 @@ final class GestureUtilities {
}
return targetVector;
}
static float[] rotate(float[] points, double angle) {
double cos = Math.cos(angle);
double sin = Math.sin(angle);
int size = points.length;
for (int i = 0; i < size; i += 2) {
float x = (float) (points[i] * cos - points[i + 1] * sin);
float y = (float) (points[i] * sin + points[i + 1] * cos);
points[i] = x;
points[i + 1] = y;
}
return points;
}
static float[] translate(float[] points, float dx, float dy) {
int size = points.length;
for (int i = 0; i < size; i += 2) {
points[i] += dx;
points[i + 1] += dy;
}
return points;
}
static float[] scale(float[] points, float sx, float sy) {
int size = points.length;
for (int i = 0; i < size; i += 2) {
points[i] *= sx;
points[i + 1] *= sy;
}
return points;
}
}

View File

@@ -16,7 +16,6 @@
package android.gesture;
import android.graphics.Matrix;
/**
* An instance represents a sample if the label is available or a query if the
@@ -28,7 +27,9 @@ class Instance {
private static final int PATCH_SAMPLE_SIZE = 16;
private final static float[] ORIENTATIONS = {
0, 45, 90, 135, 180, -0, -45, -90, -135, -180
0, (float) (Math.PI / 4), (float) (Math.PI / 2), (float) (Math.PI * 3 / 4),
(float) Math.PI, -0, (float) (-Math.PI / 4), (float) (-Math.PI / 2),
(float) (-Math.PI * 3 / 4), (float) -Math.PI
};
// the feature vector
@@ -39,13 +40,13 @@ class Instance {
// the id of the instance
final long id;
private Instance(long id, float[] sample, String sampleName) {
this.id = id;
vector = sample;
label = sampleName;
}
private void normalize() {
float[] sample = vector;
float sum = 0;
@@ -55,7 +56,7 @@ class Instance {
sum += sample[i] * sample[i];
}
float magnitude = (float) Math.sqrt(sum);
float magnitude = (float)Math.sqrt(sum);
for (int i = 0; i < size; i++) {
sample[i] /= magnitude;
}
@@ -68,11 +69,11 @@ class Instance {
* @param label
* @return the instance
*/
static Instance createInstance(int samplingType, Gesture gesture, String label) {
static Instance createInstance(int sequenceType, int orientationType, Gesture gesture, String label) {
float[] pts;
Instance instance;
if (samplingType == GestureLibrary.SEQUENCE_SENSITIVE) {
pts = temporalSampler(samplingType, gesture);
if (sequenceType == GestureStore.SEQUENCE_SENSITIVE) {
pts = temporalSampler(orientationType, gesture);
instance = new Instance(gesture.getID(), pts, label);
instance.normalize();
} else {
@@ -81,20 +82,19 @@ class Instance {
}
return instance;
}
private static float[] spatialSampler(Gesture gesture) {
return GestureUtilities.spatialSampling(gesture, PATCH_SAMPLE_SIZE);
}
private static float[] temporalSampler(int samplingType, Gesture gesture) {
private static float[] temporalSampler(int orientationType, Gesture gesture) {
float[] pts = GestureUtilities.temporalSampling(gesture.getStrokes().get(0),
SEQUENCE_SAMPLE_SIZE);
float[] center = GestureUtilities.computeCentroid(pts);
float orientation = (float) Math.atan2(pts[1] - center[1], pts[0] - center[0]);
orientation *= 180 / Math.PI;
float orientation = (float)Math.atan2(pts[1] - center[1], pts[0] - center[0]);
float adjustment = -orientation;
if (samplingType == GestureLibrary.ORIENTATION_SENSITIVE) {
if (orientationType == GestureStore.ORIENTATION_SENSITIVE) {
int count = ORIENTATIONS.length;
for (int i = 0; i < count; i++) {
float delta = ORIENTATIONS[i] - orientation;
@@ -104,10 +104,8 @@ class Instance {
}
}
Matrix m = new Matrix();
m.setTranslate(-center[0], -center[1]);
m.postRotate(adjustment);
m.mapPoints(pts);
GestureUtilities.translate(pts, -center[0], -center[1]);
GestureUtilities.rotate(pts, adjustment);
return pts;
}

View File

@@ -16,14 +16,9 @@
package android.gesture;
import android.util.Config;
import android.util.Log;
import static android.gesture.GestureConstants.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeMap;
/**
@@ -32,7 +27,7 @@ import java.util.TreeMap;
class InstanceLearner extends Learner {
@Override
ArrayList<Prediction> classify(int gestureType, float[] vector) {
ArrayList<Prediction> classify(int sequenceType, float[] vector) {
ArrayList<Prediction> predictions = new ArrayList<Prediction>();
ArrayList<Instance> instances = getInstances();
int count = instances.size();
@@ -43,7 +38,7 @@ class InstanceLearner extends Learner {
continue;
}
double distance;
if (gestureType == GestureLibrary.SEQUENCE_SENSITIVE) {
if (sequenceType == GestureStore.SEQUENCE_SENSITIVE) {
distance = GestureUtilities.cosineDistance(sample.vector, vector);
} else {
distance = GestureUtilities.squaredEuclideanDistance(sample.vector, vector);

View File

@@ -23,6 +23,7 @@ import android.util.Log;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -31,10 +32,9 @@ import java.util.HashMap;
import static android.gesture.GestureConstants.LOG_TAG;
public class LetterRecognizer {
public final static int RECOGNIZER_LATIN_LOWERCASE = 0;
static final String GESTURE_FILE_NAME = "letters.gestures";
private final static int ADJUST_RANGE = 3;
private final static int ADJUST_RANGE = 3;
private SigmoidUnit[] mHiddenLayer;
private SigmoidUnit[] mOutputLayer;
@@ -42,8 +42,8 @@ public class LetterRecognizer {
private final String[] mClasses;
private final int mPatchSize;
private GestureLibrary mGestureLibrary;
private GestureLibrary mGestureStore;
private final Comparator<Prediction> mComparator = new PredictionComparator();
@@ -69,15 +69,6 @@ public class LetterRecognizer {
}
}
public static LetterRecognizer getLetterRecognizer(Context context, int type) {
switch (type) {
case RECOGNIZER_LATIN_LOWERCASE: {
return createFromResource(context, com.android.internal.R.raw.latin_lowercase);
}
}
return null;
}
private LetterRecognizer(int numOfInput, int numOfHidden, String[] classes) {
mPatchSize = (int) Math.sqrt(numOfInput);
mHiddenLayer = new SigmoidUnit[numOfHidden];
@@ -137,14 +128,18 @@ public class LetterRecognizer {
return output;
}
private static LetterRecognizer createFromResource(Context context, int resourceID) {
static LetterRecognizer createFromResource(Context context, int resourceID) {
final Resources resources = context.getResources();
final InputStream stream = resources.openRawResource(resourceID);
return createFromStream(stream);
}
static LetterRecognizer createFromStream(InputStream stream) {
DataInputStream in = null;
LetterRecognizer classifier = null;
try {
in = new DataInputStream(new BufferedInputStream(resources.openRawResource(resourceID),
in = new DataInputStream(new BufferedInputStream(stream,
GestureConstants.IO_BUFFER_SIZE));
final int version = in.readShort();
@@ -206,49 +201,49 @@ public class LetterRecognizer {
}
/**
* TODO: Publish this API once we figure out where we should save the personzlied
* TODO: Publish this API once we figure out where we should save the personalized
* gestures, and how to do so across all apps
*
* @hide
*/
public boolean save() {
if (mGestureLibrary != null) {
return mGestureLibrary.save();
if (mGestureStore != null) {
return mGestureStore.save();
}
return false;
}
/**
* TODO: Publish this API once we figure out where we should save the personzlied
* TODO: Publish this API once we figure out where we should save the personalized
* gestures, and how to do so across all apps
*
* @hide
*/
public void setPersonalizationEnabled(boolean enabled) {
if (enabled) {
mGestureLibrary = new GestureLibrary(GESTURE_FILE_NAME);
mGestureLibrary.setSequenceType(GestureLibrary.SEQUENCE_INVARIANT);
mGestureLibrary.load();
mGestureStore = GestureLibraries.fromFile(GESTURE_FILE_NAME);
mGestureStore.setSequenceType(GestureStore.SEQUENCE_INVARIANT);
mGestureStore.load();
} else {
mGestureLibrary = null;
mGestureStore = null;
}
}
/**
* TODO: Publish this API once we figure out where we should save the personzlied
* TODO: Publish this API once we figure out where we should save the personalized
* gestures, and how to do so across all apps
*
* @hide
*/
public void addExample(String letter, Gesture example) {
if (mGestureLibrary != null) {
mGestureLibrary.addGesture(letter, example);
if (mGestureStore != null) {
mGestureStore.addGesture(letter, example);
}
}
private void adjustPrediction(Gesture query, ArrayList<Prediction> predictions) {
if (mGestureLibrary != null) {
final ArrayList<Prediction> results = mGestureLibrary.recognize(query);
if (mGestureStore != null) {
final ArrayList<Prediction> results = mGestureStore.recognize(query);
final HashMap<String, Prediction> topNList = new HashMap<String, Prediction>();
for (int j = 0; j < ADJUST_RANGE; j++) {

View File

@@ -0,0 +1,65 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.gesture;
import android.content.Context;
import android.util.Log;
import static android.gesture.GestureConstants.LOG_TAG;
import static android.gesture.LetterRecognizer.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public final class LetterRecognizers {
public final static int RECOGNIZER_LATIN_LOWERCASE = 0;
private LetterRecognizers() {
}
public static LetterRecognizer fromType(Context context, int type) {
switch (type) {
case RECOGNIZER_LATIN_LOWERCASE: {
return createFromResource(context, com.android.internal.R.raw.latin_lowercase);
}
}
return null;
}
public static LetterRecognizer fromResource(Context context, int resourceId) {
return createFromResource(context, resourceId);
}
public static LetterRecognizer fromFile(String path) {
return fromFile(new File(path));
}
public static LetterRecognizer fromFile(File file) {
try {
return createFromStream(new FileInputStream(file));
} catch (FileNotFoundException e) {
Log.d(LOG_TAG, "Failed to load handwriting data from file " + file, e);
}
return null;
}
public static LetterRecognizer fromStream(InputStream stream) {
return createFromStream(stream);
}
}

View File

@@ -18,6 +18,7 @@ package android.os;
import android.util.Log;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -35,19 +36,19 @@ import java.io.OutputStream;
public class MemoryFile
{
private static String TAG = "MemoryFile";
// returns fd
private native int native_open(String name, int length);
// returns memory address for ashmem region
private native int native_mmap(int fd, int length);
private native void native_close(int fd);
private native int native_read(int fd, int address, byte[] buffer,
int srcOffset, int destOffset, int count, boolean isUnpinned);
private native void native_write(int fd, int address, byte[] buffer,
int srcOffset, int destOffset, int count, boolean isUnpinned);
private native void native_pin(int fd, boolean pin);
private int mFD; // ashmem file descriptor
private static native FileDescriptor native_open(String name, int length) throws IOException;
// returns memory address for ashmem region
private static native int native_mmap(FileDescriptor fd, int length) throws IOException;
private static native void native_munmap(int addr, int length) throws IOException;
private static native void native_close(FileDescriptor fd);
private static native int native_read(FileDescriptor fd, int address, byte[] buffer,
int srcOffset, int destOffset, int count, boolean isUnpinned) throws IOException;
private static native void native_write(FileDescriptor fd, int address, byte[] buffer,
int srcOffset, int destOffset, int count, boolean isUnpinned) throws IOException;
private static native void native_pin(FileDescriptor fd, boolean pin) throws IOException;
private FileDescriptor mFD; // ashmem file descriptor
private int mAddress; // address of ashmem memory
private int mLength; // total length of our ashmem region
private boolean mAllowPurging = false; // true if our ashmem region is unpinned
@@ -57,8 +58,9 @@ public class MemoryFile
*
* @param name optional name for the file (can be null).
* @param length of the memory file in bytes.
* @throws IOException if the memory file could not be created.
*/
public MemoryFile(String name, int length) {
public MemoryFile(String name, int length) throws IOException {
mLength = length;
mFD = native_open(name, length);
mAddress = native_mmap(mFD, length);
@@ -68,15 +70,40 @@ public class MemoryFile
* Closes and releases all resources for the memory file.
*/
public void close() {
if (mFD > 0) {
deactivate();
if (!isClosed()) {
native_close(mFD);
mFD = 0;
}
}
private void deactivate() {
if (!isDeactivated()) {
try {
native_munmap(mAddress, mLength);
mAddress = 0;
} catch (IOException ex) {
Log.e(TAG, ex.toString());
}
}
}
/**
* Checks whether the memory file has been deactivated.
*/
private boolean isDeactivated() {
return mAddress == 0;
}
/**
* Checks whether the memory file has been closed.
*/
private boolean isClosed() {
return !mFD.valid();
}
@Override
protected void finalize() {
if (mFD > 0) {
if (!isClosed()) {
Log.e(TAG, "MemoryFile.finalize() called while ashmem still open");
close();
}
@@ -131,7 +158,6 @@ public class MemoryFile
@return OutputStream
*/
public OutputStream getOutputStream() {
return new MemoryOutputStream();
}
@@ -144,9 +170,13 @@ public class MemoryFile
* @param destOffset offset into the byte array buffer to read into.
* @param count number of bytes to read.
* @return number of bytes read.
* @throws IOException if the memory file has been purged or deactivated.
*/
public int readBytes(byte[] buffer, int srcOffset, int destOffset, int count)
throws IOException {
if (isDeactivated()) {
throw new IOException("Can't read from deactivated memory file.");
}
if (destOffset < 0 || destOffset > buffer.length || count < 0
|| count > buffer.length - destOffset
|| srcOffset < 0 || srcOffset > mLength
@@ -164,9 +194,13 @@ public class MemoryFile
* @param srcOffset offset into the byte array buffer to write from.
* @param destOffset offset into the memory file to write to.
* @param count number of bytes to write.
* @throws IOException if the memory file has been purged or deactivated.
*/
public void writeBytes(byte[] buffer, int srcOffset, int destOffset, int count)
throws IOException {
if (isDeactivated()) {
throw new IOException("Can't write to deactivated memory file.");
}
if (srcOffset < 0 || srcOffset > buffer.length || count < 0
|| count > buffer.length - srcOffset
|| destOffset < 0 || destOffset > mLength

View File

@@ -151,6 +151,9 @@ public class CallLog {
int presentation, int callType, long start, int duration) {
final ContentResolver resolver = context.getContentResolver();
// TODO(Moto): Which is correct: original code, this only changes the
// number if the number is empty and never changes the caller info name.
if (false) {
if (TextUtils.isEmpty(number)) {
if (presentation == Connection.PRESENTATION_RESTRICTED) {
number = CallerInfo.PRIVATE_NUMBER;
@@ -160,7 +163,22 @@ public class CallLog {
number = CallerInfo.UNKNOWN_NUMBER;
}
}
} else {
// NEWCODE: From Motorola
//If this is a private number then set the number to Private, otherwise check
//if the number field is empty and set the number to Unavailable
if (presentation == Connection.PRESENTATION_RESTRICTED) {
number = CallerInfo.PRIVATE_NUMBER;
ci.name = "";
} else if (presentation == Connection.PRESENTATION_PAYPHONE) {
number = CallerInfo.PAYPHONE_NUMBER;
ci.name = "";
} else if (TextUtils.isEmpty(number) || presentation == Connection.PRESENTATION_UNKNOWN) {
number = CallerInfo.UNKNOWN_NUMBER;
ci.name = "";
}
}
ContentValues values = new ContentValues(5);
values.put(NUMBER, number);

View File

@@ -0,0 +1,616 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.provider;
import android.graphics.BitmapFactory;
import android.net.Uri;
/**
* The contract between the contacts provider and applications. Contains definitions
* for the supported URIs and columns.
*
* @hide
*/
public final class ContactsContract {
/** The authority for the contacts provider */
public static final String AUTHORITY = "com.android.contacts";
/** A content:// style uri to the authority for the contacts provider */
public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
public interface AggregatesColumns {
/**
* The display name for the contact.
* <P>Type: TEXT</P>
*/
public static final String DISPLAY_NAME = "display_name";
/**
* The number of times a person has been contacted
* <P>Type: INTEGER</P>
*/
public static final String TIMES_CONTACTED = "times_contacted";
/**
* The last time a person was contacted.
* <P>Type: INTEGER</P>
*/
public static final String LAST_TIME_CONTACTED = "last_time_contacted";
/**
* Is the contact starred?
* <P>Type: INTEGER (boolean)</P>
*/
public static final String STARRED = "starred";
/**
* Reference to the row in the data table holding the primary phone number.
* <P>Type: INTEGER REFERENCES data(_id)</P>
*/
public static final String PRIMARY_PHONE_ID = "primary_phone_id";
/**
* Reference to the row in the data table holding the primary email address.
* <P>Type: INTEGER REFERENCES data(_id)</P>
*/
public static final String PRIMARY_EMAIL_ID = "primary_email_id";
/**
* Reference to the row in the data table holding the photo.
* <P>Type: INTEGER REFERENCES data(_id)</P>
*/
public static final String PHOTO_ID = "photo_id";
/**
* Reference to a row containing custom ringtone and send to voicemail information.
* <P>Type: INTEGER REFERENCES data(_id)</P>
*/
public static final String CUSTOM_RINGTONE_ID = "custom_ringtone_id";
}
/**
* Constants for the aggregates table, which contains a record per group
* of contact representing the same person.
*/
public static final class Aggregates implements BaseColumns, AggregatesColumns {
/**
* This utility class cannot be instantiated
*/
private Aggregates() {}
/**
* The content:// style URI for this table
*/
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "aggregates");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* people.
*/
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person_aggregate";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* person.
*/
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person_aggregate";
/**
* A sub-directory of a single contact aggregate that contains all of their
* {@link Data} rows.
*/
public static final class Data implements BaseColumns, DataColumns {
/**
* no public constructor since this is a utility class
*/
private Data() {}
/**
* The directory twig for this sub-table
*/
public static final String CONTENT_DIRECTORY = "data";
}
}
/**
* Constants for the contacts table, which contains the base contact information.
*/
public static final class Contacts implements BaseColumns {
/**
* This utility class cannot be instantiated
*/
private Contacts() {}
/**
* A reference to the {@link Aggregates#_ID} that this data belongs to.
*/
public static final String AGGREGATE_ID = "aggregate_id";
/**
* The content:// style URI for this table
*/
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contacts");
/**
* The content:// style URL for filtering people by email address. The
* filter argument should be passed as an additional path segment after
* this URI.
*
* @hide
*/
public static final Uri CONTENT_FILTER_EMAIL_URI = Uri.withAppendedPath(CONTENT_URI, "filter_email");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of
* people.
*/
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* person.
*/
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person";
/**
* A sub-directory of a single contact that contains all of their {@link Data} rows.
* To access this directory append
*/
public static final class Data implements BaseColumns, DataColumns {
/**
* no public constructor since this is a utility class
*/
private Data() {}
/**
* The directory twig for this sub-table
*/
public static final String CONTENT_DIRECTORY = "data";
}
}
private interface DataColumns {
/**
* The package name that defines this type of data.
*/
public static final String PACKAGE = "package";
/**
* The mime-type of the item represented by this row.
*/
public static final String MIMETYPE = "mimetype";
/**
* A reference to the {@link android.provider.ContactsContract.Contacts#_ID}
* that this data belongs to.
*/
public static final String CONTACT_ID = "contact_id";
/** Generic data column, the meaning is {@link #MIMETYPE} specific */
public static final String DATA1 = "data1";
/** Generic data column, the meaning is {@link #MIMETYPE} specific */
public static final String DATA2 = "data2";
/** Generic data column, the meaning is {@link #MIMETYPE} specific */
public static final String DATA3 = "data3";
/** Generic data column, the meaning is {@link #MIMETYPE} specific */
public static final String DATA4 = "data4";
/** Generic data column, the meaning is {@link #MIMETYPE} specific */
public static final String DATA5 = "data5";
/** Generic data column, the meaning is {@link #MIMETYPE} specific */
public static final String DATA6 = "data6";
/** Generic data column, the meaning is {@link #MIMETYPE} specific */
public static final String DATA7 = "data7";
/** Generic data column, the meaning is {@link #MIMETYPE} specific */
public static final String DATA8 = "data8";
/** Generic data column, the meaning is {@link #MIMETYPE} specific */
public static final String DATA9 = "data9";
/** Generic data column, the meaning is {@link #MIMETYPE} specific */
public static final String DATA10 = "data10";
}
/**
* Constants for the data table, which contains data points tied to a contact.
* For example, a phone number or email address. Each row in this table contains a type
* definition and some generic columns. Each data type can define the meaning for each of
* the generic columns.
*/
public static final class Data implements BaseColumns, DataColumns {
/**
* This utility class cannot be instantiated
*/
private Data() {}
/**
* The content:// style URI for this table
*/
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "data");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of data.
*/
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data";
}
/**
* A table that represents the result of looking up a phone number, for example for caller ID.
* The table joins that data row for the phone number with the contact that owns the number.
* To perform a lookup you must append the number you want to find to {@link #CONTENT_URI}.
*/
public static final class PhoneLookup implements BaseColumns, DataColumns, AggregatesColumns {
/**
* This utility class cannot be instantiated
*/
private PhoneLookup() {}
/**
* The content:// style URI for this table. Append the phone number you want to lookup
* to this URI and query it to perform a lookup. For example:
*
* {@code
* Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_URI, phoneNumber);
* }
*/
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "phone_lookup");
}
/**
* Container for definitions of common data types stored in the {@link Data} table.
*/
public static final class CommonDataKinds {
/**
* The {@link Data#PACKAGE} value for common data that should be shown
* using a default style.
*/
public static final String PACKAGE_COMMON = "common";
/**
* Columns common across the specific types.
*/
private interface BaseCommonColumns {
/**
* The package name that defines this type of data.
*/
public static final String PACKAGE = "package";
/**
* The mime-type of the item represented by this row.
*/
public static final String MIMETYPE = "mimetype";
/**
* A reference to the {@link android.provider.ContactsContract.Contacts#_ID} that this
* data belongs to.
*/
public static final String CONTACT_ID = "contact_id";
}
/**
* Columns common across the specific types.
*/
private interface CommonColumns {
/**
* The type of data, for example Home or Work.
* <P>Type: INTEGER</P>
*/
public static final String TYPE = "data1";
/**
* The user defined label for the the contact method.
* <P>Type: TEXT</P>
*/
public static final String LABEL = "data2";
/**
* The data for the contact method.
* <P>Type: TEXT</P>
*/
public static final String DATA = "data3";
/**
* Whether this is the primary entry of its kind for the contact it belongs to
* <P>Type: INTEGER (if set, non-0 means true)</P>
*/
public static final String ISPRIMARY = "data4";
}
/**
* Parts of the name.
*/
public static final class StructuredName {
private StructuredName() {}
/** Mime-type used when storing this in data table. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name";
/**
* The contact's honorific prefix, e.g. "Sir"
*/
public static final String PREFIX = "data1";
/**
* The given name for the contact.
* <P>Type: TEXT</P>
*/
public static final String GIVEN_NAME = "data2";
/**
* The contact's middle name
* <P>Type: TEXT</P>
*/
public static final String MIDDLE_NAME = "data3";
/**
* The family name for the contact.
* <P>Type: TEXT</P>
*/
public static final String FAMILY_NAME = "data4";
/**
* The contact's honorific suffix, e.g. "Jr"
*/
public static final String SUFFIX = "data5";
/**
* The phonetic version of the given name for the contact.
* <P>Type: TEXT</P>
*/
public static final String PHONETIC_GIVEN_NAME = "data6";
/**
* The phonetic version of the additional name for the contact.
* <P>Type: TEXT</P>
*/
public static final String PHONETIC_MIDDLE_NAME = "data7";
/**
* The phonetic version of the family name for the contact.
* <P>Type: TEXT</P>
*/
public static final String PHONETIC_FAMILY_NAME = "data8";
/**
* The name that should be used to display the contact.
* <P>Type: TEXT</P>
*/
public static final String DISPLAY_NAME = "data9";
}
/**
* A nickname.
*/
public static final class Nickname {
private Nickname() {}
/** Mime-type used when storing this in data table. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname";
/**
* The type of data, for example Home or Work.
* <P>Type: INTEGER</P>
*/
public static final String TYPE = "data1";
public static final int TYPE_CUSTOM = 1;
public static final int TYPE_DEFAULT = 2;
public static final int TYPE_OTHER_NAME = 3;
public static final int TYPE_MAINDEN_NAME = 4;
public static final int TYPE_SHORT_NAME = 5;
public static final int TYPE_INITIALS = 6;
/**
* The user provided label, only used if TYPE is {@link #TYPE_CUSTOM}.
* <P>Type: TEXT</P>
*/
public static final String LABEL = "data2";
/**
* The name itself
*/
public static final String NAME = "data3";
}
/**
* Common data definition for telephone numbers.
*/
public static final class Phone implements BaseCommonColumns, CommonColumns {
private Phone() {}
/** Mime-type used when storing this in data table. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone";
public static final int TYPE_CUSTOM = 0;
public static final int TYPE_HOME = 1;
public static final int TYPE_MOBILE = 2;
public static final int TYPE_WORK = 3;
public static final int TYPE_FAX_WORK = 4;
public static final int TYPE_FAX_HOME = 5;
public static final int TYPE_PAGER = 6;
public static final int TYPE_OTHER = 7;
/**
* The phone number as the user entered it.
* <P>Type: TEXT</P>
*/
public static final String NUMBER = "data3";
}
/**
* Common data definition for email addresses.
*/
public static final class Email implements BaseCommonColumns, CommonColumns {
private Email() {}
/** Mime-type used when storing this in data table. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email";
public static final int TYPE_CUSTOM = 0;
public static final int TYPE_HOME = 1;
public static final int TYPE_WORK = 2;
public static final int TYPE_OTHER = 3;
}
/**
* Common data definition for postal addresses.
*/
public static final class Postal implements BaseCommonColumns, CommonColumns {
private Postal() {}
/** Mime-type used when storing this in data table. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/postal-address";
public static final int TYPE_CUSTOM = 0;
public static final int TYPE_HOME = 1;
public static final int TYPE_WORK = 2;
public static final int TYPE_OTHER = 3;
}
/**
* Common data definition for IM addresses.
*/
public static final class Im implements BaseCommonColumns, CommonColumns {
private Im() {}
/** Mime-type used when storing this in data table. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im";
public static final int TYPE_CUSTOM = 0;
public static final int TYPE_HOME = 1;
public static final int TYPE_WORK = 2;
public static final int TYPE_OTHER = 3;
public static final String PROTOCOL = "data5";
/**
* The predefined IM protocol types. The protocol can either be non-present, one
* of these types, or a free-form string. These cases are encoded in the PROTOCOL
* column as:
* - null
* - pre:<an integer, one of the protocols below>
* - custom:<a string>
*/
public static final int PROTOCOL_AIM = 0;
public static final int PROTOCOL_MSN = 1;
public static final int PROTOCOL_YAHOO = 2;
public static final int PROTOCOL_SKYPE = 3;
public static final int PROTOCOL_QQ = 4;
public static final int PROTOCOL_GOOGLE_TALK = 5;
public static final int PROTOCOL_ICQ = 6;
public static final int PROTOCOL_JABBER = 7;
}
/**
* Common data definition for organizations.
*/
public static final class Organization implements BaseCommonColumns {
private Organization() {}
/** Mime-type used when storing this in data table. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization";
/**
* The type of data, for example Home or Work.
* <P>Type: INTEGER</P>
*/
public static final String TYPE = "data1";
public static final int TYPE_CUSTOM = 0;
public static final int TYPE_HOME = 1;
public static final int TYPE_WORK = 2;
public static final int TYPE_OTHER = 3;
/**
* The user provided label, only used if TYPE is {@link #TYPE_CUSTOM}.
* <P>Type: TEXT</P>
*/
public static final String LABEL = "data2";
/**
* The company as the user entered it.
* <P>Type: TEXT</P>
*/
public static final String COMPANY = "data3";
/**
* The position title at this company as the user entered it.
* <P>Type: TEXT</P>
*/
public static final String TITLE = "data4";
/**
* Whether this is the primary organization
* <P>Type: INTEGER (if set, non-0 means true)</P>
*/
public static final String ISPRIMARY = "data5";
}
/**
* Photo of the contact.
*/
public static final class Photo implements BaseCommonColumns {
private Photo() {}
/** Mime-type used when storing this in data table. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
/**
* Thumbnail photo of the contact. This is the raw bytes of an image
* that could be inflated using {@link BitmapFactory}.
* <p>
* Type: BLOB
*/
public static final String PHOTO = "data1";
}
/**
* Notes about the contact.
*/
public static final class Note implements BaseCommonColumns {
private Note() {}
/** Mime-type used when storing this in data table. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note";
/**
* The note text.
* <P>Type: TEXT</P>
*/
public static final String NOTE = "data1";
}
public static final class CustomRingtone implements BaseCommonColumns {
private CustomRingtone() {}
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/custom_ringtone";
/**
* Whether to send the number to voicemail.
* <P>Type: INTEGER (if set, non-0 means true)</P>
*/
public static final String SEND_TO_VOICEMAIL = "data1";
/**
* The ringtone uri.
* <P>Type: TEXT</P>
*/
public static final String RINGTONE_URI = "data2";
}
}
}

View File

@@ -2854,12 +2854,12 @@ public final class Settings {
* out without asking for use permit, to limit the un-authorized SMS
* usage.
*/
public static final String SMS_OUTGOING_CEHCK_INTERVAL_MS =
public static final String SMS_OUTGOING_CHECK_INTERVAL_MS =
"sms_outgoing_check_interval_ms";
/**
* The number of outgoing SMS sent without asking for user permit
* (of {@link #SMS_OUTGOING_CEHCK_INTERVAL_MS}
* (of {@link #SMS_OUTGOING_CHECK_INTERVAL_MS}
*/
public static final String SMS_OUTGOING_CEHCK_MAX_COUNT =
"sms_outgoing_check_max_count";

View File

@@ -0,0 +1,174 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.provider;
import android.graphics.BitmapFactory;
import android.net.Uri;
/**
* The contract between the social provider and applications. Contains
* definitions for the supported URIs and columns.
*
* @hide
*/
public class SocialContract {
/** The authority for the social provider */
public static final String AUTHORITY = "com.android.social";
/** A content:// style uri to the authority for the contacts provider */
public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
private interface ActivitiesColumns {
/**
* The package name that owns this social activity.
* <p>
* Type: TEXT
*/
public static final String PACKAGE = "package";
/**
* The mime-type of this social activity.
* <p>
* Type: TEXT
*/
public static final String MIMETYPE = "mimetype";
/**
* Internal raw identifier for this social activity. This field is
* analogous to the <code>atom:id</code> element defined in RFC 4287.
* <p>
* Type: TEXT
*/
public static final String RAW_ID = "raw_id";
/**
* Reference to another {@link Activities#RAW_ID} that this social activity
* is replying to. This field is analogous to the
* <code>thr:in-reply-to</code> element defined in RFC 4685.
* <p>
* Type: TEXT
*/
public static final String IN_REPLY_TO = "in_reply_to";
/**
* Reference to the {@link android.provider.ContactsContract.Contacts#_ID} that authored
* this social activity. This field is analogous to the <code>atom:author</code>
* element defined in RFC 4287.
* <p>
* Type: INTEGER
*/
public static final String AUTHOR_CONTACT_ID = "author_contact_id";
/**
* Optional reference to the {@link android.provider.ContactsContract.Contacts#_ID} this
* social activity is targeted towards. If more than one direct target, this field may
* be left undefined. This field is analogous to the
* <code>activity:target</code> element defined in the Atom Activity
* Extensions Internet-Draft.
* <p>
* Type: INTEGER
*/
public static final String TARGET_CONTACT_ID = "target_contact_id";
/**
* Timestamp when this social activity was published, in a
* {@link System#currentTimeMillis()} time base. This field is analogous
* to the <code>atom:published</code> element defined in RFC 4287.
* <p>
* Type: INTEGER
*/
public static final String PUBLISHED = "published";
/**
* Timestamp when the original social activity in a thread was
* published. For activities that have an in-reply-to field specified, the
* content provider will automatically populate this field with the
* timestamp of the original activity.
* <p>
* This field is useful for sorting order of activities that keeps together all
* messages in each thread.
* <p>
* Type: INTEGER
*/
public static final String THREAD_PUBLISHED = "thread_published";
/**
* Title of this social activity. This field is analogous to the
* <code>atom:title</code> element defined in RFC 4287.
* <p>
* Type: TEXT
*/
public static final String TITLE = "title";
/**
* Summary of this social activity. This field is analogous to the
* <code>atom:summary</code> element defined in RFC 4287.
* <p>
* Type: TEXT
*/
public static final String SUMMARY = "summary";
/**
* A URI associated this social activity. This field is analogous to the
* <code>atom:link rel="alternate"</code> element defined in RFC 4287.
* <p>
* Type: TEXT
*/
public static final String LINK = "link";
/**
* Optional thumbnail specific to this social activity. This is the raw
* bytes of an image that could be inflated using {@link BitmapFactory}.
* <p>
* Type: BLOB
*/
public static final String THUMBNAIL = "thumbnail";
}
public static final class Activities implements BaseColumns, ActivitiesColumns {
/**
* This utility class cannot be instantiated
*/
private Activities() {
}
/**
* The content:// style URI for this table
*/
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "activities");
/**
* The content:// style URI for this table filtered to the set of social activities
* authored by a specific {@link android.provider.ContactsContract.Contacts#_ID}.
*/
public static final Uri CONTENT_AUTHORED_BY_URI =
Uri.withAppendedPath(CONTENT_URI, "authored_by");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of social
* activities.
*/
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/activity";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* social activity.
*/
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/activity";
}
}

View File

@@ -465,6 +465,24 @@ public final class Telephony {
* Contains info about SMS related Intents that are broadcast.
*/
public static final class Intents {
/**
* Set by BroadcastReceiver. Indicates the message was handled
* successfully.
*/
public static final int RESULT_SMS_HANDLED = 1;
/**
* Set by BroadcastReceiver. Indicates a generic error while
* processing the message.
*/
public static final int RESULT_SMS_GENERIC_ERROR = 2;
/**
* Set by BroadcastReceiver. Indicates insufficient memory to store
* the message.
*/
public static final int RESULT_SMS_OUT_OF_MEMORY = 3;
/**
* Broadcast Action: A new text based SMS message has been received
* by the device. The intent will have the following extra
@@ -476,7 +494,10 @@ public final class Telephony {
* </ul>
*
* <p>The extra values can be extracted using
* {@link #getMessagesFromIntent(Intent)}</p>
* {@link #getMessagesFromIntent(Intent)}.</p>
*
* <p>If a BroadcastReceiver encounters an error while processing
* this intent it should set the result code appropriately.</p>
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String SMS_RECEIVED_ACTION =
@@ -493,7 +514,10 @@ public final class Telephony {
* </ul>
*
* <p>The extra values can be extracted using
* {@link #getMessagesFromIntent(Intent)}</p>
* {@link #getMessagesFromIntent(Intent)}.</p>
*
* <p>If a BroadcastReceiver encounters an error while processing
* this intent it should set the result code appropriately.</p>
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String DATA_SMS_RECEIVED_ACTION =
@@ -510,6 +534,9 @@ public final class Telephony {
* <li><em>pduType (Integer)</em> - The WAP PDU type</li>
* <li><em>data</em> - The data payload of the message</li>
* </ul>
*
* <p>If a BroadcastReceiver encounters an error while processing
* this intent it should set the result code appropriately.</p>
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String WAP_PUSH_RECEIVED_ACTION =

View File

@@ -17,6 +17,7 @@
package android.speech;
import android.os.Bundle;
import android.speech.RecognitionResult;
/**
* Listener for speech recognition events, used with RecognitionService.
@@ -43,13 +44,19 @@ interface IRecognitionListener {
/** Called after the user stops speaking. */
void onEndOfSpeech();
/** A network or recognition error occurred. */
void onError(in String error);
/**
* A network or recognition error occurred.
* TODO: right now, the error code is given in voice search package
* (vendor/google/apps/src/com/google/android/voicesearch/speechservice/SpeechServiceListener.java)
* we need to find a place to define common error code.
*/
void onError(in int error);
/**
* Called when recognition transcripts are ready.
* results: an ordered list of the most likely transcripts (N-best list).
* @hide
* Called when recognition results are ready.
* @param results: an ordered list of the most likely results (N-best list).
* @param key: a key associated with the results. The same results can
* be retrieved asynchronously later using the key, if available.
*/
void onResults(in List<String> results);
void onResults(in List<RecognitionResult> results, long key);
}

View File

@@ -18,6 +18,7 @@ package android.speech;
import android.content.Intent;
import android.speech.IRecognitionListener;
import android.speech.RecognitionResult;
// A Service interface to speech recognition. Call startListening when
// you want to begin capturing audio; RecognitionService will automatically
@@ -29,6 +30,8 @@ interface IRecognitionService {
// see RecognizerIntent.java for constants used to specify the intent.
void startListening(in Intent recognizerIntent,
in IRecognitionListener listener);
List<RecognitionResult> getRecognitionResults(in long key);
void cancel();
}

View File

@@ -0,0 +1,19 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.speech;
parcelable RecognitionResult;

View File

@@ -0,0 +1,151 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package android.speech;
import android.os.Parcel;
import android.os.Parcelable;
/**
* RecognitionResult is a passive object that stores a single recognized
* query and its search result.
* TODO: revisit and improve. May be we should have a separate result
* object for each type, and put them (type/value) in bundle?
*
* {@hide}
*/
public class RecognitionResult implements Parcelable {
/**
* Type of the recognition results.
*/
public static final int RAW_RECOGNITION_RESULT = 0;
public static final int WEB_SEARCH_RESULT = 1;
public static final int CONTACT_RESULT = 2;
/**
* A factory method to create a raw RecognitionResult
*
* @param sentence the recognized text.
*/
public static RecognitionResult newRawRecognitionResult(String sentence) {
return new RecognitionResult(RAW_RECOGNITION_RESULT, sentence, null, null);
}
/**
* A factory method to create RecognitionResult for contacts.
*
* @param contact the contact name.
* @param phoneType the phone type.
*/
public static RecognitionResult newContactResult(String contact, int phoneType) {
return new RecognitionResult(CONTACT_RESULT, contact, phoneType);
}
/**
* A factory method to create a RecognitionResult for Web Search Query.
*
* @param query the query string.
* @param html the html page of the search result.
* @param url the url that performs the search with the query.
*/
public static RecognitionResult newWebResult(String query, String html, String url) {
return new RecognitionResult(WEB_SEARCH_RESULT, query, html, url);
}
public static final Parcelable.Creator<RecognitionResult> CREATOR
= new Parcelable.Creator<RecognitionResult>() {
public RecognitionResult createFromParcel(Parcel in) {
return new RecognitionResult(in);
}
public RecognitionResult[] newArray(int size) {
return new RecognitionResult[size];
}
};
/**
* Result type.
*/
public final int mResultType;
/**
* The recognized string when mResultType is WEB_SEARCH_RESULT.
* The name of the contact when mResultType is CONTACT_RESULT.
*/
public final String mText;
/**
* The HTML result page for the query. If this is null, then the
* application must use the url field to get the HTML result page.
*/
public final String mHtml;
/**
* The url to get the result page for the query string. The
* application must use this url instead of performing the search
* with the query.
*/
public final String mUrl;
/** Phone number type. This is valid only when mResultType == CONTACT_RESULT */
public final int mPhoneType;
private RecognitionResult(int type, String query, String html, String url) {
mResultType = type;
mText = query;
mHtml = html;
mUrl = url;
mPhoneType = -1;
}
private RecognitionResult(int type, String query, int at) {
mResultType = type;
mText = query;
mPhoneType = at;
mHtml = null;
mUrl = null;
}
private RecognitionResult(Parcel in) {
mResultType = in.readInt();
mText = in.readString();
mHtml= in.readString();
mUrl= in.readString();
mPhoneType = in.readInt();
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mResultType);
out.writeString(mText);
out.writeString(mHtml);
out.writeString(mUrl);
out.writeInt(mPhoneType);
}
@Override
public String toString() {
String resultType[] = { "RAW", "WEB", "CONTACT" };
return "[type=" + resultType[mResultType] +
", text=" + mText+ ", mUrl=" + mUrl + ", html=" + mHtml + "]";
}
public int describeContents() {
// no special description
return 0;
}
}

View File

@@ -21,6 +21,9 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.speech.RecognitionResult;
import android.util.Log;
import java.util.List;
@@ -56,6 +59,11 @@ public class RecognitionServiceUtil {
public static final Intent sDefaultIntent = new Intent(
RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
// Recognize request parameters
public static final String USE_LOCATION = "useLocation";
public static final String CONTACT_AUTH_TOKEN = "contactAuthToken";
// Bundles
public static final String NOISE_LEVEL = "NoiseLevel";
public static final String SIGNAL_NOISE_RATIO = "SignalNoiseRatio";
@@ -72,8 +80,8 @@ public class RecognitionServiceUtil {
public void onRmsChanged(float rmsdB) {}
public void onBufferReceived(byte[] buf) {}
public void onEndOfSpeech() {}
public void onError(String error) {}
public void onResults(List<String> results) {}
public void onError(int error) {}
public void onResults(List<RecognitionResult> results, long key) {}
}
/**

View File

@@ -106,7 +106,7 @@ public class DialerKeyListener extends NumberKeyListener
*/
public static final char[] CHARACTERS = new char[] {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '*',
'+', '-', '(', ')', ',', '/', 'N', '.', ' '
'+', '-', '(', ')', ',', '/', 'N', '.', ' ', ';'
};
private static DialerKeyListener sInstance;

View File

@@ -370,6 +370,9 @@ public class WebView extends AbsoluteLayout
// Whether or not to draw the focus ring.
private boolean mDrawFocusRing = true;
// true if onPause has been called (and not onResume)
private boolean mIsPaused;
/**
* Customizable constant
*/
@@ -997,7 +1000,7 @@ public class WebView extends AbsoluteLayout
/**
* If platform notifications are enabled, this should be called
* from onPause() or onStop().
* from the Activity's onPause() or onStop().
*/
public static void disablePlatformNotifications() {
Network.disablePlatformNotifications();
@@ -1938,21 +1941,58 @@ public class WebView extends AbsoluteLayout
}
/**
* Pause all layout, parsing, and javascript timers. This can be useful if
* the WebView is not visible or the application has been paused.
* Pause all layout, parsing, and javascript timers for all webviews. This
* is a global requests, not restricted to just this webview. This can be
* useful if the application has been paused.
*/
public void pauseTimers() {
mWebViewCore.sendMessage(EventHub.PAUSE_TIMERS);
}
/**
* Resume all layout, parsing, and javascript timers. This will resume
* dispatching all timers.
* Resume all layout, parsing, and javascript timers for all webviews.
* This will resume dispatching all timers.
*/
public void resumeTimers() {
mWebViewCore.sendMessage(EventHub.RESUME_TIMERS);
}
/**
* Call this to pause any extra processing associated with this view and
* its associated DOM/plugins/javascript/etc. For example, if the view is
* taken offscreen, this could be called to reduce unnecessary CPU and/or
* network traffic. When the view is again "active", call onResume().
*
* Note that this differs from pauseTimers(), which affects all views/DOMs
* @hide
*/
public void onPause() {
if (!mIsPaused) {
mIsPaused = true;
mWebViewCore.sendMessage(EventHub.ON_PAUSE);
}
}
/**
* Call this to balanace a previous call to onPause()
* @hide
*/
public void onResume() {
if (mIsPaused) {
mIsPaused = false;
mWebViewCore.sendMessage(EventHub.ON_RESUME);
}
}
/**
* Returns true if the view is paused, meaning onPause() was called. Calling
* onResume() sets the paused state back to false.
* @hide
*/
public boolean isPaused() {
return mIsPaused;
}
/**
* Clear the resource cache. Note that the cache is per-application, so
* this will clear the cache for all WebViews used.

View File

@@ -591,6 +591,8 @@ final class WebViewCore {
"TOUCH_UP", // = 140;
"TOUCH_EVENT", // = 141;
"SET_ACTIVE", // = 142;
"ON_PAUSE", // = 143
"ON_RESUME", // = 144
};
class EventHub {
@@ -647,6 +649,11 @@ final class WebViewCore {
// or not, based on whether the WebView has focus.
static final int SET_ACTIVE = 142;
// pause/resume activity for just this DOM (unlike pauseTimers, which
// is global)
static final int ON_PAUSE = 143;
static final int ON_RESUME = 144;
// Network-based messaging
static final int CLEAR_SSL_PREF_TABLE = 150;
@@ -841,6 +848,14 @@ final class WebViewCore {
}
break;
case ON_PAUSE:
nativePause();
break;
case ON_RESUME:
nativeResume();
break;
case SET_NETWORK_STATE:
if (BrowserFrame.sJavaBridge == null) {
throw new IllegalStateException("No WebView " +
@@ -1750,4 +1765,7 @@ final class WebViewCore {
}
}
private native void nativePause();
private native void nativeResume();
}

View File

@@ -52,6 +52,7 @@ import android.gesture.GestureOverlayView;
import android.gesture.Gesture;
import android.gesture.LetterRecognizer;
import android.gesture.Prediction;
import android.gesture.LetterRecognizers;
import com.android.internal.R;
@@ -94,7 +95,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
public static final int TRANSCRIPT_MODE_NORMAL = 1;
/**
* The list will automatically scroll to the bottom, no matter what items
* are currently visible.
* are currently visible.
*
* @see #setTranscriptMode(int)
*/
@@ -156,7 +157,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* Indicates the view is in the process of being flung
*/
static final int TOUCH_MODE_FLING = 4;
/**
* Indicates that the user is currently dragging the fast scroll thumb
*/
@@ -349,7 +350,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* bitmap cache after scrolling.
*/
boolean mScrollingCacheEnabled;
/**
* Whether or not to enable the fast scroll feature on this list
*/
@@ -422,7 +423,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* The last CheckForTap runnable we posted, if any
*/
private Runnable mPendingCheckForTap;
/**
* The last CheckForKeyLongPress runnable we posted, if any
*/
@@ -576,7 +577,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
int color = a.getColor(R.styleable.AbsListView_cacheColorHint, 0);
setCacheColorHint(color);
boolean enableFastScroll = a.getBoolean(R.styleable.AbsListView_fastScrollEnabled, false);
setFastScrollEnabled(enableFastScroll);
@@ -605,7 +606,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
mDensityScale = getContext().getResources().getDisplayMetrics().density;
}
/**
* <p>Sets the type of gestures to use with this list. When gestures are enabled,
* that is if the <code>gestures</code> parameter is not {@link #GESTURES_NONE},
@@ -663,7 +664,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* @see #GESTURES_NONE
* @see #GESTURES_JUMP
* @see #GESTURES_FILTER
* @see #setGestures(int)
* @see #setGestures(int)
*/
@ViewDebug.ExportedProperty(mapping = {
@ViewDebug.IntToString(from = GESTURES_NONE, to = "NONE"),
@@ -737,7 +738,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mGesturesOverlay.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);
mGesturesOverlay.addOnGesturePerformedListener(new GesturesProcessor());
mPreviousGesturing = false;
mPreviousGesturing = false;
}
}
@@ -778,10 +779,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
/**
* Enables fast scrolling by letting the user quickly scroll through lists by
* dragging the fast scroll thumb. The adapter attached to the list may want
* Enables fast scrolling by letting the user quickly scroll through lists by
* dragging the fast scroll thumb. The adapter attached to the list may want
* to implement {@link SectionIndexer} if it wishes to display alphabet preview and
* jump between sections of the list.
* jump between sections of the list.
* @see SectionIndexer
* @see #isFastScrollEnabled()
* @param enabled whether or not to enable fast scrolling
@@ -799,7 +800,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
}
/**
* Returns the current state of the fast scroll feature.
* @see #setFastScrollEnabled(boolean)
@@ -809,10 +810,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
public boolean isFastScrollEnabled() {
return mFastScrollEnabled;
}
/**
* If fast scroll is visible, then don't draw the vertical scrollbar.
* @hide
* @hide
*/
@Override
protected boolean isVerticalScrollBarHidden() {
@@ -830,11 +831,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* When smooth scrollbar is disabled, the position and size of the scrollbar thumb
* is based solely on the number of items in the adapter and the position of the
* visible items inside the adapter. This provides a stable scrollbar as the user
* navigates through a list of items with varying heights.
* navigates through a list of items with varying heights.
*
* @param enabled Whether or not to enable smooth scrollbar.
*
* @see #setSmoothScrollbarEnabled(boolean)
* @see #setSmoothScrollbarEnabled(boolean)
* @attr ref android.R.styleable#AbsListView_smoothScrollbar
*/
public void setSmoothScrollbarEnabled(boolean enabled) {
@@ -1142,7 +1143,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
/**
* Sets the initial value for the text filter.
* @param filterText The text to use for the filter.
*
*
* @see #setTextFilterEnabled
*/
public void setFilterText(String filterText) {
@@ -1168,7 +1169,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
/**
* Returns the list's text filter, if available.
* Returns the list's text filter, if available.
* @return the list's text filter or null if filtering isn't enabled
*/
public CharSequence getTextFilter() {
@@ -1177,7 +1178,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
return null;
}
@Override
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
@@ -1570,7 +1571,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (mInstallGesturesOverlay) {
installGesturesOverlay();
positionGesturesPopup();
} else if (mGesturesPopup != null) {
} else if (mGesturesPopup != null && mGesturesPopup.isShowing()) {
mGesturesPopup.update(w, h);
}
}
@@ -1740,7 +1741,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
System.arraycopy(state, enabledPos + 1, state, enabledPos,
state.length - enabledPos - 1);
}
return state;
}
@@ -1851,16 +1852,16 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
*/
private class WindowRunnnable {
private int mOriginalAttachCount;
public void rememberWindowAttachCount() {
mOriginalAttachCount = getWindowAttachCount();
}
public boolean sameWindow() {
return hasWindowFocus() && getWindowAttachCount() == mOriginalAttachCount;
}
}
private class PerformClick extends WindowRunnnable implements Runnable {
View mChild;
int mClickMotionPosition;
@@ -1887,7 +1888,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
final long longPressId = mAdapter.getItemId(mMotionPosition);
boolean handled = false;
if (sameWindow() && !mDataChanged) {
if (sameWindow() && !mDataChanged) {
handled = performLongPress(child, longPressPosition, longPressId);
}
if (handled) {
@@ -1901,7 +1902,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
}
private class CheckForKeyLongPress extends WindowRunnnable implements Runnable {
public void run() {
if (isPressed() && mSelectedPosition >= 0) {
@@ -1930,7 +1931,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
boolean handled = false;
dismissGesturesPopup();
if (mOnItemLongClickListener != null) {
handled = mOnItemLongClickListener.onItemLongClick(AbsListView.this, child,
longPressPosition, longPressId);
@@ -2079,7 +2080,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mTouchMode = TOUCH_MODE_DONE_WAITING;
}
} else {
mTouchMode = TOUCH_MODE_DONE_WAITING;
mTouchMode = TOUCH_MODE_DONE_WAITING;
}
}
}
@@ -2138,7 +2139,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
boolean intercepted = mFastScroller.onTouchEvent(ev);
if (intercepted) {
return true;
}
}
}
final int action = ev.getAction();
@@ -2326,10 +2327,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
setPressed(false);
// Need to redraw since we probably aren't drawing the selector anymore
invalidate();
final Handler handler = getHandler();
if (handler != null) {
handler.removeCallbacks(mPendingCheckForLongPress);
@@ -2373,7 +2374,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
return true;
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
@@ -2388,14 +2389,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
int x = (int) ev.getX();
int y = (int) ev.getY();
View v;
if (mFastScroller != null) {
boolean intercepted = mFastScroller.onInterceptTouchEvent(ev);
if (intercepted) {
return true;
}
}
switch (action) {
case MotionEvent.ACTION_DOWN: {
int motionPosition = findMotionRow(y);
@@ -3245,7 +3246,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
return null;
}
/**
* For filtering we proxy an input connection to an internal text editor,
* and this allows the proxying to happen.
@@ -3254,7 +3255,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
public boolean checkInputConnectionProxy(View view) {
return view == mTextFilter;
}
/**
* Creates the window for the text filter and populates it with an EditText field;
*
@@ -3647,7 +3648,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mCurrentScrap = scrapViews[0];
mScrapViews = scrapViews;
}
public boolean shouldRecycleViewType(int viewType) {
return viewType >= 0;
}
@@ -3862,11 +3863,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
private final char[] mHolder;
GesturesProcessor() {
mRecognizer = LetterRecognizer.getLetterRecognizer(getContext(),
LetterRecognizer.RECOGNIZER_LATIN_LOWERCASE);
mRecognizer = LetterRecognizers.fromType(getContext(),
LetterRecognizers.RECOGNIZER_LATIN_LOWERCASE);
if (mRecognizer == null) {
dismissGesturesPopup();
mGestures = GESTURES_NONE;
setGestures(GESTURES_NONE);
}
if (mGestures == GESTURES_FILTER) {
mKeyMap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);

View File

@@ -2851,9 +2851,15 @@ public class ListView extends AbsListView {
final int first = mFirstPosition;
final boolean areAllItemsSelectable = mAreAllItemsSelectable;
final ListAdapter adapter = mAdapter;
final boolean isOpaque = isOpaque();
if (isOpaque && mDividerPaint == null) {
// If the list is opaque *and* the background is not, we want to
// fill a rect where the dividers would be for non-selectable items
// If the list is opaque and the background is also opaque, we don't
// need to draw anything since the background will do it for us
final boolean fillForMissingDividers = isOpaque() && !super.isOpaque();
if (fillForMissingDividers && mDividerPaint == null && mIsCacheColorOpaque) {
mDividerPaint = new Paint();
mDividerPaint.setColor(getCacheColorHint());
}
final Paint paint = mDividerPaint;
@@ -2874,7 +2880,7 @@ public class ListView extends AbsListView {
bounds.top = bottom;
bounds.bottom = bottom + dividerHeight;
drawDivider(canvas, bounds, i);
} else if (isOpaque) {
} else if (fillForMissingDividers) {
bounds.top = bottom;
bounds.bottom = bottom + dividerHeight;
canvas.drawRect(bounds, paint);
@@ -2903,7 +2909,7 @@ public class ListView extends AbsListView {
// position. Give -1 when there is no child above the
// divider.
drawDivider(canvas, bounds, i - 1);
} else if (isOpaque) {
} else if (fillForMissingDividers) {
bounds.top = top - dividerHeight;
bounds.bottom = top;
canvas.drawRect(bounds, paint);

View File

@@ -87,8 +87,9 @@ public class TabHost extends FrameLayout implements ViewTreeObserver.OnTouchMode
/**
* <p>Call setup() before adding tabs if loading TabHost using findViewById(). <i><b>However</i></b>: You do
* not need to call setup() after getTabHost() in {@link android.app.TabActivity TabActivity}.
* <p>Call setup() before adding tabs if loading TabHost using findViewById().
* <i><b>However</i></b>: You do not need to call setup() after getTabHost()
* in {@link android.app.TabActivity TabActivity}.
* Example:</p>
<pre>mTabHost = (TabHost)findViewById(R.id.tabhost);
mTabHost.setup();
@@ -363,14 +364,14 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
*
* @param tag
* Which tab was selected.
* @return The view to distplay the contents of the selected tab.
* @return The view to display the contents of the selected tab.
*/
View createTabContent(String tag);
}
/**
* A tab has a tab indictor, content, and a tag that is used to keep
* A tab has a tab indicator, content, and a tag that is used to keep
* track of it. This builder helps choose among these options.
*
* For the tab indicator, your choices are:
@@ -607,7 +608,7 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
}
mLaunchedView = wd;
// XXX Set FOCUS_AFTER_DESCENDANTS on embedded activies for now so they can get
// XXX Set FOCUS_AFTER_DESCENDANTS on embedded activities for now so they can get
// focus if none of their children have it. They need focus to be able to
// display menu items.
//

View File

@@ -53,7 +53,7 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
private static final int VERSION = 36;
private static final int VERSION = 37;
private final File mFile;
private final File mBackupFile;
@@ -3014,6 +3014,8 @@ public final class BatteryStatsImpl extends BatteryStats {
u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL);