merge master to master_gl
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
139
core/java/android/gesture/GestureLibraries.java
Normal file
139
core/java/android/gesture/GestureLibraries.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
330
core/java/android/gesture/GestureStore.java
Normal file
330
core/java/android/gesture/GestureStore.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
65
core/java/android/gesture/LetterRecognizers.java
Normal file
65
core/java/android/gesture/LetterRecognizers.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
616
core/java/android/provider/ContactsContract.java
Normal file
616
core/java/android/provider/ContactsContract.java
Normal 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";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
174
core/java/android/provider/SocialContract.java
Normal file
174
core/java/android/provider/SocialContract.java
Normal 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";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
19
core/java/android/speech/RecognitionResult.aidl
Normal file
19
core/java/android/speech/RecognitionResult.aidl
Normal 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;
|
||||
151
core/java/android/speech/RecognitionResult.java
Normal file
151
core/java/android/speech/RecognitionResult.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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) {}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
//
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user