diff options
Diffstat (limited to 'tests')
33 files changed, 1279 insertions, 1910 deletions
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java index b3e88e1..f8d5d4d 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java @@ -136,6 +136,81 @@ public class CdmaSmsTest extends AndroidTestCase { } @SmallTest + public void testUserDataHeaderConcatRefFeedback() throws Exception { + BearerData bearerData = new BearerData(); + bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER; + bearerData.messageId = 55; + SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); + concatRef.refNumber = 0xEE; + concatRef.msgCount = 2; + concatRef.seqNumber = 2; + concatRef.isEightBits = true; + SmsHeader smsHeader = new SmsHeader(); + smsHeader.concatRef = concatRef; + byte[] encodedHeader = SmsHeader.toByteArray(smsHeader); + SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader); + assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber); + assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount); + assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber); + assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits); + assertEquals(decodedHeader.portAddrs, null); + UserData userData = new UserData(); + userData.payloadStr = "User Data Header (UDH) feedback test"; + userData.userDataHeader = smsHeader; + bearerData.userData = userData; + byte[] encodedSms = BearerData.encode(bearerData); + BearerData revBearerData = BearerData.decode(encodedSms); + decodedHeader = revBearerData.userData.userDataHeader; + assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber); + assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount); + assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber); + assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits); + assertEquals(decodedHeader.portAddrs, null); + } + + @SmallTest + public void testUserDataHeaderMixedFeedback() throws Exception { + BearerData bearerData = new BearerData(); + bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER; + bearerData.messageId = 42; + SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); + concatRef.refNumber = 0x34; + concatRef.msgCount = 5; + concatRef.seqNumber = 2; + concatRef.isEightBits = false; + SmsHeader.PortAddrs portAddrs = new SmsHeader.PortAddrs(); + portAddrs.destPort = 88; + portAddrs.origPort = 66; + portAddrs.areEightBits = false; + SmsHeader smsHeader = new SmsHeader(); + smsHeader.concatRef = concatRef; + smsHeader.portAddrs = portAddrs; + byte[] encodedHeader = SmsHeader.toByteArray(smsHeader); + SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader); + assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber); + assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount); + assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber); + assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits); + assertEquals(decodedHeader.portAddrs.destPort, portAddrs.destPort); + assertEquals(decodedHeader.portAddrs.origPort, portAddrs.origPort); + assertEquals(decodedHeader.portAddrs.areEightBits, portAddrs.areEightBits); + UserData userData = new UserData(); + userData.payloadStr = "User Data Header (UDH) feedback test"; + userData.userDataHeader = smsHeader; + bearerData.userData = userData; + byte[] encodedSms = BearerData.encode(bearerData); + BearerData revBearerData = BearerData.decode(encodedSms); + decodedHeader = revBearerData.userData.userDataHeader; + assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber); + assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount); + assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber); + assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits); + assertEquals(decodedHeader.portAddrs.destPort, portAddrs.destPort); + assertEquals(decodedHeader.portAddrs.origPort, portAddrs.origPort); + assertEquals(decodedHeader.portAddrs.areEightBits, portAddrs.areEightBits); + } + + @SmallTest public void testReplyOption() throws Exception { String pdu1 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87450080a0180"; BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1)); diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java index d775dc2..f623080 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java @@ -509,9 +509,14 @@ public class DatabaseGeneralTest extends TestCase implements PerformanceTestCase Cursor c; mDatabase.execSQL("CREATE TABLE tokens (" + "token TEXT COLLATE unicode," + - "source INTEGER " + + "source INTEGER," + + "token_index INTEGER," + + "tag TEXT" + + ");"); + mDatabase.execSQL("CREATE TABLE tokens_no_index (" + + "token TEXT COLLATE unicode," + + "source INTEGER" + ");"); - String[] cols = new String[]{"token", "source"}; Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, "SELECT _TOKENIZE(NULL, NULL, NULL, NULL)", null)); @@ -523,60 +528,152 @@ public class DatabaseGeneralTest extends TestCase implements PerformanceTestCase "SELECT _TOKENIZE('tokens', 10, 'some string', NULL)", null)); Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase, - "SELECT _TOKENIZE('tokens', 1, 'some string ok', ' ')", null)); - + "SELECT _TOKENIZE('tokens', 11, 'some string ok', ' ', 1, 'foo')", null)); + Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, + "SELECT _TOKENIZE('tokens', 11, 'second field', ' ', 1, 'bar')", null)); + + Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase, + "SELECT _TOKENIZE('tokens_no_index', 20, 'some string ok', ' ')", null)); + Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase, + "SELECT _TOKENIZE('tokens_no_index', 21, 'foo bar baz', ' ', 0)", null)); + // test Chinese String chinese = new String("\u4eac\u4ec5 \u5c3d\u5f84\u60ca"); Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, - "SELECT _TOKENIZE('tokens', 1,'" + chinese + "', ' ')", null)); + "SELECT _TOKENIZE('tokens', 12,'" + chinese + "', ' ', 1)", null)); String icustr = new String("Fr\u00e9d\u00e9ric Hj\u00f8nnev\u00e5g"); Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, - "SELECT _TOKENIZE('tokens', 1, '" + icustr + "', ' ')", null)); + "SELECT _TOKENIZE('tokens', 13, '" + icustr + "', ' ', 1)", null)); - Assert.assertEquals(7, DatabaseUtils.longForQuery(mDatabase, + Assert.assertEquals(9, DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from tokens;", null)); String key = DatabaseUtils.getHexCollationKey("Frederic Hjonneva"); Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(13, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); key = DatabaseUtils.getHexCollationKey("Hjonneva"); Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(13, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); key = DatabaseUtils.getHexCollationKey("some string ok"); Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase, + "SELECT tag from tokens where token GLOB '" + key + "*'", null)); key = DatabaseUtils.getHexCollationKey("string"); Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase, + "SELECT tag from tokens where token GLOB '" + key + "*'", null)); key = DatabaseUtils.getHexCollationKey("ok"); Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); - + Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase, + "SELECT tag from tokens where token GLOB '" + key + "*'", null)); + + key = DatabaseUtils.getHexCollationKey("second field"); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals("bar", DatabaseUtils.stringForQuery(mDatabase, + "SELECT tag from tokens where token GLOB '" + key + "*'", null)); + key = DatabaseUtils.getHexCollationKey("field"); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals("bar", DatabaseUtils.stringForQuery(mDatabase, + "SELECT tag from tokens where token GLOB '" + key + "*'", null)); + key = DatabaseUtils.getHexCollationKey(chinese); String[] a = new String[1]; a[0] = key; Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from tokens where token= ?", a)); + Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token= ?", a)); + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token= ?", a)); a[0] += "*"; Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from tokens where token GLOB ?", a)); + Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token GLOB ?", a)); + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token GLOB ?", a)); Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from tokens where token= '" + key + "'", null)); + Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token= '" + key + "'", null)); + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token= '" + key + "'", null)); Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); key = DatabaseUtils.getHexCollationKey("\u4eac\u4ec5"); Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); + key = DatabaseUtils.getHexCollationKey("\u5c3d\u5f84\u60ca"); + Log.d("DatabaseGeneralTest", "key = " + key); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens where token GLOB '" + key + "*'", null)); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, "SELECT count(*) from tokens where token GLOB 'ab*'", null)); + + key = DatabaseUtils.getHexCollationKey("some string ok"); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens_no_index where token GLOB '" + key + "*'", null)); + Assert.assertEquals(20, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens_no_index where token GLOB '" + key + "*'", null)); + + key = DatabaseUtils.getHexCollationKey("bar"); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens_no_index where token GLOB '" + key + "*'", null)); + Assert.assertEquals(21, DatabaseUtils.longForQuery(mDatabase, + "SELECT source from tokens_no_index where token GLOB '" + key + "*'", null)); } @MediumTest diff --git a/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java b/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java index 360352b..9d44fd9 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java @@ -69,10 +69,15 @@ public class SMSTest extends AndroidTestCase { SmsHeader header = sms.getUserDataHeader(); assertNotNull(header); - - Iterator<SmsHeader.Element> elements = header.getElements().iterator(); - assertNotNull(elements); - + assertNotNull(header.concatRef); + assertEquals(header.concatRef.refNumber, 42); + assertEquals(header.concatRef.msgCount, 2); + assertEquals(header.concatRef.seqNumber, 1); + assertEquals(header.concatRef.isEightBits, true); + assertNotNull(header.portAddrs); + assertEquals(header.portAddrs.destPort, 2948); + assertEquals(header.portAddrs.origPort, 9200); + assertEquals(header.portAddrs.areEightBits, false); pdu = "07914140279510F6440A8111110301003BF56080207130238A3B0B05040B8423F" + "000032A0202362E3130322E3137312E3135302F524E453955304A6D7135514141" @@ -81,9 +86,15 @@ public class SMSTest extends AndroidTestCase { header = sms.getUserDataHeader(); assertNotNull(header); - - elements = header.getElements().iterator(); - assertNotNull(elements); + assertNotNull(header.concatRef); + assertEquals(header.concatRef.refNumber, 42); + assertEquals(header.concatRef.msgCount, 2); + assertEquals(header.concatRef.seqNumber, 2); + assertEquals(header.concatRef.isEightBits, true); + assertNotNull(header.portAddrs); + assertEquals(header.portAddrs.destPort, 2948); + assertEquals(header.portAddrs.origPort, 9200); + assertEquals(header.portAddrs.areEightBits, false); /* * UCS-2 encoded SMS diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ContentProviderOperationTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/ContentProviderOperationTest.java new file mode 100644 index 0000000..46a12fd --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/content/ContentProviderOperationTest.java @@ -0,0 +1,211 @@ +/* + * 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 com.android.unit_tests.content; + +import android.test.suitebuilder.annotation.SmallTest; +import android.net.Uri; +import android.content.ContentValues; +import android.content.ContentProviderOperation; +import android.content.OperationApplicationException; +import android.content.ContentProviderResult; +import android.content.ContentProvider; +import android.text.TextUtils; +import android.database.Cursor; +import junit.framework.TestCase; + +import java.util.Map; +import java.util.Hashtable; + +@SmallTest +public class ContentProviderOperationTest extends TestCase { + private final static Uri sTestUri1 = Uri.parse("content://authority/blah"); + private final static ContentValues sTestValues1; + + static { + sTestValues1 = new ContentValues(); + sTestValues1.put("a", 1); + sTestValues1.put("b", "two"); + } + + public void testInsert() throws OperationApplicationException { + ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1) + .withValues(sTestValues1) + .build(); + ContentProviderResult result = op1.apply(new TestContentProvider() { + public Uri insert(Uri uri, ContentValues values) { + assertEquals(sTestUri1.toString(), uri.toString()); + assertEquals(sTestValues1.toString(), values.toString()); + return uri.buildUpon().appendPath("19").build(); + } + }, null, 0); + assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString()); + } + + public void testInsertNoValues() throws OperationApplicationException { + ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1) + .build(); + ContentProviderResult result = op1.apply(new TestContentProvider() { + public Uri insert(Uri uri, ContentValues values) { + assertEquals(sTestUri1.toString(), uri.toString()); + assertNull(values); + return uri.buildUpon().appendPath("19").build(); + } + }, null, 0); + assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString()); + } + + public void testInsertFailed() { + ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1) + .withValues(sTestValues1) + .build(); + try { + op1.apply(new TestContentProvider() { + public Uri insert(Uri uri, ContentValues values) { + assertEquals(sTestUri1.toString(), uri.toString()); + assertEquals(sTestValues1.toString(), values.toString()); + return null; + } + }, null, 0); + fail("the apply should have thrown an OperationApplicationException"); + } catch (OperationApplicationException e) { + // this is the expected case + } + } + + public void testInsertWithBackRefs() throws OperationApplicationException { + ContentValues valuesBackRefs = new ContentValues(); + valuesBackRefs.put("a1", 3); + valuesBackRefs.put("a2", 1); + + ContentProviderResult[] previousResults = new ContentProviderResult[4]; + previousResults[0] = new ContentProviderResult(100); + previousResults[1] = new ContentProviderResult(101); + previousResults[2] = new ContentProviderResult(102); + previousResults[3] = new ContentProviderResult(103); + ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1) + .withValues(sTestValues1) + .withValueBackReferences(valuesBackRefs) + .build(); + ContentProviderResult result = op1.apply(new TestContentProvider() { + public Uri insert(Uri uri, ContentValues values) { + assertEquals(sTestUri1.toString(), uri.toString()); + ContentValues expected = new ContentValues(sTestValues1); + expected.put("a1", 103); + expected.put("a2", 101); + assertEquals(expected.toString(), values.toString()); + return uri.buildUpon().appendPath("19").build(); + } + }, previousResults, previousResults.length); + assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString()); + } + + public void testUpdate() throws OperationApplicationException { + ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1) + .withValues(sTestValues1) + .build(); + ContentProviderResult[] backRefs = new ContentProviderResult[2]; + ContentProviderResult result = op1.apply(new TestContentProvider() { + public Uri insert(Uri uri, ContentValues values) { + assertEquals(sTestUri1.toString(), uri.toString()); + assertEquals(sTestValues1.toString(), values.toString()); + return uri.buildUpon().appendPath("19").build(); + } + }, backRefs, 1); + assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString()); + } + + public void testValueBackRefs() { + ContentValues values = new ContentValues(); + values.put("a", "in1"); + values.put("a2", "in2"); + values.put("b", "in3"); + values.put("c", "in4"); + + ContentProviderResult[] previousResults = new ContentProviderResult[4]; + previousResults[0] = new ContentProviderResult(100); + previousResults[1] = new ContentProviderResult(101); + previousResults[2] = new ContentProviderResult(102); + previousResults[3] = new ContentProviderResult(103); + + ContentValues valuesBackRefs = new ContentValues(); + valuesBackRefs.put("a1", 3); // a1 -> 103 + valuesBackRefs.put("a2", 1); // a2 -> 101 + valuesBackRefs.put("a3", 2); // a3 -> 102 + + ContentValues expectedValues = new ContentValues(values); + expectedValues.put("a1", "103"); + expectedValues.put("a2", "101"); + expectedValues.put("a3", "102"); + + ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1) + .withValues(values) + .withValueBackReferences(valuesBackRefs) + .build(); + ContentValues v2 = op1.resolveValueBackReferences(previousResults, previousResults.length); + assertEquals(expectedValues, v2); + } + + public void testSelectionBackRefs() { + Map<Integer, Integer> selectionBackRefs = new Hashtable<Integer, Integer>(); + selectionBackRefs.put(1, 3); + selectionBackRefs.put(2, 1); + selectionBackRefs.put(4, 2); + + ContentProviderResult[] previousResults = new ContentProviderResult[4]; + previousResults[0] = new ContentProviderResult(100); + previousResults[1] = new ContentProviderResult(101); + previousResults[2] = new ContentProviderResult(102); + previousResults[3] = new ContentProviderResult(103); + + String[] selectionArgs = new String[]{"a", null, null, "b", null}; + + ContentProviderOperation op1 = ContentProviderOperation.newUpdate(sTestUri1) + .withSelectionBackReferences(selectionBackRefs) + .withSelection("unused", selectionArgs) + .build(); + String[] s2 = op1.resolveSelectionArgsBackReferences( + previousResults, previousResults.length); + assertEquals("a,103,101,b,102", TextUtils.join(",", s2)); + } + + static class TestContentProvider extends ContentProvider { + public boolean onCreate() { + throw new UnsupportedOperationException(); + } + + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + throw new UnsupportedOperationException(); + } + + public String getType(Uri uri) { + throw new UnsupportedOperationException(); + } + + public Uri insert(Uri uri, ContentValues values) { + throw new UnsupportedOperationException(); + } + + public int delete(Uri uri, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException(); + } + + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException(); + } + } +}
\ No newline at end of file diff --git a/tests/CoreTests/android/location/LocationManagerProximityTest.java b/tests/CoreTests/android/location/LocationManagerProximityTest.java index 3f43bcf..e82d878 100644 --- a/tests/CoreTests/android/location/LocationManagerProximityTest.java +++ b/tests/CoreTests/android/location/LocationManagerProximityTest.java @@ -26,6 +26,7 @@ import android.location.LocationManager; import android.provider.Settings; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.Suppress; import android.util.Log; /** @@ -37,9 +38,11 @@ import android.util.Log; * adb shell am instrument -e class android.location.LocationManagerProximityTest \ * -w android.core/android.test.InstrumentationTestRunner * - * This test requires that the "Allow mock locations" setting be enabled + * This test requires that the "Allow mock locations" setting be enabled. + * To ensure reliable results, all location providers should be disabled. * */ +@Suppress @MediumTest public class LocationManagerProximityTest extends AndroidTestCase { diff --git a/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java b/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java index 5df8991..e2336f8 100644 --- a/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java +++ b/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java @@ -28,18 +28,20 @@ public class GsmAlphabetTest extends TestCase { @SmallTest public void test7bitWithHeader() throws Exception { - byte[] data = new byte[3]; - data[0] = (byte) 1; - data[1] = (byte) 2; - data[2] = (byte) 2; + SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef(); + concatRef.refNumber = 1; + concatRef.seqNumber = 2; + concatRef.msgCount = 2; + concatRef.isEightBits = true; SmsHeader header = new SmsHeader(); - header.add(new SmsHeader.Element(SmsHeader.CONCATENATED_8_BIT_REFERENCE, data)); + header.concatRef = concatRef; - String message = "aaaaaaaaaabbbbbbbbbbcccccccccc"; - byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header.toByteArray()); + String message = "aaaaaaaaaabbbbbbbbbbcccccccccc"; + byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, + SmsHeader.toByteArray(header)); int septetCount = GsmAlphabet.countGsmSeptets(message, false); String parsedMessage = GsmAlphabet.gsm7BitPackedToString( - userData, header.toByteArray().length+1, septetCount, 1); + userData, SmsHeader.toByteArray(header).length+1, septetCount, 1); assertEquals(message, parsedMessage); } @@ -306,4 +308,3 @@ public class GsmAlphabetTest extends TestCase { GsmAlphabet.gsm8BitUnpackedToString(unpacked, 1, unpacked.length - 1)); } } - diff --git a/tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java b/tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java index 5d5d1f9..8a66614 100644 --- a/tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java +++ b/tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java @@ -34,35 +34,38 @@ public class SMSDispatcherTest extends AndroidTestCase { public void testCMT1() throws Exception { SmsMessage sms; SmsHeader header; - Iterator<SmsHeader.Element> elements; String[] lines = new String[2]; - - lines[0] = "+CMT: ,158"; + + lines[0] = "+CMT: ,158"; lines[1] = "07914140279510F6440A8111110301003BF56080426101748A8C0B05040B" + "8423F000035502010106276170706C69636174696F6E2F766E642E776170" + "2E6D6D732D6D65737361676500AF848D0185B4848C8298524F347839776F" + "7547514D4141424C3641414141536741415A4B554141414141008D908918" + "802B31363530323438363137392F545950453D504C4D4E008A808E028000" + "88058103093A8083687474703A2F2F36"; - + sms = SmsMessage.newFromCMT(lines); header = sms.getUserDataHeader(); assertNotNull(header); assertNotNull(sms.getUserData()); - - elements = header.getElements().iterator(); - assertNotNull(elements); + assertNotNull(header.concatRef); + assertEquals(header.concatRef.refNumber, 85); + assertEquals(header.concatRef.msgCount, 2); + assertEquals(header.concatRef.seqNumber, 1); + assertEquals(header.concatRef.isEightBits, true); + assertNotNull(header.portAddrs); + assertEquals(header.portAddrs.destPort, 2948); + assertEquals(header.portAddrs.origPort, 9200); + assertEquals(header.portAddrs.areEightBits, false); } - + @MediumTest public void testCMT2() throws Exception { SmsMessage sms; SmsHeader header; - Iterator<SmsHeader.Element> elements; String[] lines = new String[2]; - lines[0] = "+CMT: ,77"; lines[1] = "07914140279510F6440A8111110301003BF56080426101848A3B0B05040B8423F" @@ -71,12 +74,17 @@ public class SMSDispatcherTest extends AndroidTestCase { sms = SmsMessage.newFromCMT(lines); header = sms.getUserDataHeader(); - System.out.println("header = " + header); assertNotNull(header); assertNotNull(sms.getUserData()); - - elements = header.getElements().iterator(); - assertNotNull(elements); + assertNotNull(header.concatRef); + assertEquals(header.concatRef.refNumber, 85); + assertEquals(header.concatRef.msgCount, 2); + assertEquals(header.concatRef.seqNumber, 2); + assertEquals(header.concatRef.isEightBits, true); + assertNotNull(header.portAddrs); + assertEquals(header.portAddrs.destPort, 2948); + assertEquals(header.portAddrs.origPort, 9200); + assertEquals(header.portAddrs.areEightBits, false); } @MediumTest diff --git a/tests/DumpRenderTree/AndroidManifest.xml b/tests/DumpRenderTree/AndroidManifest.xml index 0e33d62..5442ec9 100644 --- a/tests/DumpRenderTree/AndroidManifest.xml +++ b/tests/DumpRenderTree/AndroidManifest.xml @@ -31,5 +31,6 @@ android:targetPackage="com.android.dumprendertree" android:label="Layout test automation runner" /> - <uses-permission android:name="android.permission.INTERNET"></uses-permission> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.WRITE_SDCARD" /> </manifest> diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java index caef861..f169a26 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java @@ -223,7 +223,10 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh } private String getExpectedResultFile(String test) { - String shortName = test.substring(0, test.lastIndexOf('.')); + int pos = test.lastIndexOf('.'); + if(pos == -1) + return null; + String shortName = test.substring(0, pos); return shortName + "-expected.txt"; } @@ -303,6 +306,10 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh }); String resultFile = getResultFile(test); + if(resultFile == null) { + //simply ignore this test + return; + } if (mRebaselineResults) { String expectedResultFile = getExpectedResultFile(test); File f = new File(expectedResultFile); diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java index 81cf3a8..c792e8e 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java @@ -69,11 +69,14 @@ public class LoadTestsAutoTest extends ActivityInstrumentationTestCase2<TestShel TestShellActivity activity = (TestShellActivity) getActivity(); + Log.v(LOGTAG, "About to run tests, calling gc first..."); + Runtime.getRuntime().runFinalization(); + Runtime.getRuntime().gc(); + Runtime.getRuntime().gc(); + // Run tests runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis); - // TODO(fqian): let am instrumentation pass in the command line, currently - // am instrument does not allow spaces in the command. dumpMemoryInfo(); // Kill activity @@ -82,6 +85,11 @@ public class LoadTestsAutoTest extends ActivityInstrumentationTestCase2<TestShel private void dumpMemoryInfo() { try { + Log.v(LOGTAG, "About to dump meminfo, calling gc first..."); + Runtime.getRuntime().runFinalization(); + Runtime.getRuntime().gc(); + Runtime.getRuntime().gc(); + Log.v(LOGTAG, "Dumping memory information."); FileOutputStream out = new FileOutputStream(LOAD_TEST_RESULT, true); diff --git a/tests/backup/Android.mk b/tests/backup/Android.mk index 2e3385f..0813c35 100644 --- a/tests/backup/Android.mk +++ b/tests/backup/Android.mk @@ -21,7 +21,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ backup_helper_test.cpp -LOCAL_MODULE_TAGS := user +LOCAL_MODULE_TAGS := optional LOCAL_MODULE := backup_helper_test LOCAL_SHARED_LIBRARIES := libutils @@ -31,7 +31,7 @@ include $(BUILD_EXECUTABLE) # ======================================== include $(CLEAR_VARS) -LOCAL_MODULE_TAGS := user +LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-subdir-java-files) diff --git a/tests/backup/backup_helper_test.cpp b/tests/backup/backup_helper_test.cpp index 66240e3..1085909 100644 --- a/tests/backup/backup_helper_test.cpp +++ b/tests/backup/backup_helper_test.cpp @@ -23,6 +23,7 @@ Test TESTS[] = { { "backup_helper_test_four", backup_helper_test_four, 0, false }, { "backup_helper_test_files", backup_helper_test_files, 0, false }, { "backup_helper_test_data_writer", backup_helper_test_data_writer, 0, false }, + { "backup_helper_test_data_reader", backup_helper_test_data_reader, 0, false }, { 0, NULL, 0, false} }; diff --git a/tests/sketch/AndroidManifest.xml b/tests/sketch/AndroidManifest.xml index c44b54e..fbf3a09 100755 --- a/tests/sketch/AndroidManifest.xml +++ b/tests/sketch/AndroidManifest.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2008 The Android Open Source Project +<!-- 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. @@ -14,17 +14,32 @@ limitations under the License. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.gesture" - android:versionCode="1" - android:versionName="1.0.0"> - <application android:icon="@drawable/icon" android:label="@string/app_name"> - <activity android:name="com.android.gesture.example.GestureEntryDemo" - android:label="@string/app_name"> + package="com.android.gesture.example"> + + <uses-permission android:name="android.permission.READ_CONTACTS" /> + <uses-permission android:name="android.permission.WRITE_SDCARD" /> + + <application android:icon="@drawable/icon" android:label="@string/app_name"> + + <activity + android:name="com.android.gesture.example.GestureEntry" + android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + <activity android:name="com.android.gesture.example.GestureLibViewer"/> + + <activity + android:name="com.android.gesture.example.ContactListGestureOverlay" + android:label="@string/overlay_name"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> </manifest> diff --git a/tests/sketch/res/layout/demo.xml b/tests/sketch/res/layout/demo.xml index e516229..8c9161a 100755 --- a/tests/sketch/res/layout/demo.xml +++ b/tests/sketch/res/layout/demo.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2008 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. @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. --> + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" @@ -24,7 +25,7 @@ android:drawSelectorOnTop="true" android:prompt="@string/recognition_result"/> - <com.android.gesture.GesturePad + <com.android.gesture.GestureOverlay android:id="@+id/drawingpad" android:layout_width="fill_parent" android:layout_height="wrap_content" diff --git a/tests/sketch/res/layout/gestureviewer.xml b/tests/sketch/res/layout/gestureviewer.xml index 5302d34..73d6a35 100755 --- a/tests/sketch/res/layout/gestureviewer.xml +++ b/tests/sketch/res/layout/gestureviewer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2008 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. @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. --> + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" @@ -25,7 +26,7 @@ android:drawSelectorOnTop="true" android:prompt="@string/recognition_result"/> - <com.android.gesture.GesturePad + <com.android.gesture.GestureOverlay android:id="@+id/drawingpad" android:layout_width="fill_parent" android:layout_height="wrap_content" diff --git a/tests/sketch/res/layout/newgesture_dialog.xml b/tests/sketch/res/layout/newgesture_dialog.xml index 6e45d81..91e7645 100755 --- a/tests/sketch/res/layout/newgesture_dialog.xml +++ b/tests/sketch/res/layout/newgesture_dialog.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2008 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. diff --git a/tests/sketch/res/layout/overlaydemo.xml b/tests/sketch/res/layout/overlaydemo.xml new file mode 100644 index 0000000..b6bbab3 --- /dev/null +++ b/tests/sketch/res/layout/overlaydemo.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > + <ListView + android:id="@+id/list" + android:layout_width="fill_parent" + android:layout_height="0dip" + android:layout_weight="1"/> +</LinearLayout> diff --git a/tests/sketch/res/values/strings.xml b/tests/sketch/res/values/strings.xml index 4c6aa20..42f14da 100755 --- a/tests/sketch/res/values/strings.xml +++ b/tests/sketch/res/values/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2008 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. @@ -15,6 +15,7 @@ --> <resources> <string name="app_name">Gesture Demo</string> + <string name="overlay_name">Overlay Demo</string> <string name="recognition_result">Recognition Result</string> <string name="clear">Clear</string> <string name="newgesture">Add</string> diff --git a/tests/sketch/src/com/android/gesture/Gesture.java b/tests/sketch/src/com/android/gesture/Gesture.java deleted file mode 100755 index 29c07ad..0000000 --- a/tests/sketch/src/com/android/gesture/Gesture.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * 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 com.android.gesture; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.PointF; -import android.graphics.RectF; -import android.os.Parcel; -import android.os.Parcelable; - -import com.android.gesture.recognizer.RecognitionUtil; - -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.StringTokenizer; - -/** - * A single stroke gesture. - */ - -public class Gesture implements Parcelable { - - private RectF mBBX; - private float mLength = 0; - private int mColor; - private float mWidth; - private ArrayList<PointF> mPtsBuffer = new ArrayList<PointF>(); - private long mTimestamp = 0; - private long mID; - - private static final long systemStartupTime = System.currentTimeMillis(); - private static int instanceCount = 0; - - public Gesture() { - mID = systemStartupTime + instanceCount++; - } - - public void setColor(int c) { - mColor = c; - } - - public void setStrokeWidth(float w) { - mWidth = w; - } - - public int getColor() { - return mColor; - } - - public float getStrokeWidth() { - return mWidth; - } - - public ArrayList<PointF> getPoints() { - return this.mPtsBuffer; - } - - public int numOfPoints() { - return this.mPtsBuffer.size(); - } - - public void addPoint(float x, float y) { - mPtsBuffer.add(new PointF(x, y)); - if (mBBX == null) { - mBBX = new RectF(); - mBBX.top = y; - mBBX.left = x; - mBBX.right = x; - mBBX.bottom = y; - mLength = 0; - } - else { - PointF lst = mPtsBuffer.get(mPtsBuffer.size()-2); - mLength += Math.sqrt(Math.pow(x-lst.x, 2)+Math.pow(y-lst.y, 2)); - mBBX.union(x, y); - } - mTimestamp = System.currentTimeMillis(); - } - - /** - * @return the length of the gesture - */ - public float getLength() { - return this.mLength; - } - - public RectF getBBX() { - return mBBX; - } - - public void setID(long id) { - mID = id; - } - - public long getID() { - return mID; - } - - public long getTimeStamp() { - return mTimestamp; - } - - public void setTimestamp(long t) { - this.mTimestamp = t; - } - - /** - * draw the gesture - * @param canvas - */ - public void draw(Canvas canvas) { - Paint paint = new Paint(); - paint.setAntiAlias(true); - paint.setDither(true); - paint.setColor(mColor); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeJoin(Paint.Join.ROUND); - paint.setStrokeCap(Paint.Cap.ROUND); - paint.setStrokeWidth(mWidth); - - Path path = null; - float mX = 0, mY = 0; - Iterator<PointF> it = mPtsBuffer.iterator(); - while (it.hasNext()) { - PointF p = it.next(); - float x = p.x; - float y = p.y; - if (path == null) { - path = new Path(); - path.moveTo(x, y); - mX = x; - mY = y; - } else { - float dx = Math.abs(x - mX); - float dy = Math.abs(y - mY); - if (dx >= 3 || dy >= 3) { - path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2); - mX = x; - mY = y; - } - } - } - - canvas.drawPath(path, paint); - } - - /** - * convert the gesture to a Path - * @param width the width of the bounding box of the target path - * @param height the height of the bounding box of the target path - * @param numSample the num of points needed - * @return the path - */ - public Path toPath(float width, float height, int numSample) { - float[] pts = RecognitionUtil.resample(this, numSample); - RectF rect = this.getBBX(); - float scale = height / rect.height(); - Matrix matrix = new Matrix(); - matrix.setTranslate(-rect.left, -rect.top); - Matrix scalem = new Matrix(); - scalem.setScale(scale, scale); - matrix.postConcat(scalem); - Matrix translate = new Matrix(); - matrix.postConcat(translate); - matrix.mapPoints(pts); - - Path path = null; - float mX = 0, mY = 0; - for (int i=0; i<pts.length-1; i+=2) { - float x = pts[i]; - float y = pts[i+1]; - if (path == null) { - path = new Path(); - path.moveTo(x, y); - mX = x; - mY = y; - } else { - float dx = Math.abs(x - mX); - float dy = Math.abs(y - mY); - if (dx >= 3 || dy >= 3) { - path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2); - mX = x; - mY = y; - } - } - } - return path; - } - - /** - * get a bitmap thumbnail of the gesture with a transparent background - * @param w - * @param h - * @param edge - * @param numSample - * @param foreground - * @return - */ - public Bitmap toBitmap(int w, int h, - int edge, int numSample) { - RectF bbx = this.getBBX(); - Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - Path path = this.toPath(w - 2 * edge, h - 2 * edge, numSample); - Canvas c = new Canvas(bitmap); - //c.drawColor(background); - c.translate(edge, edge); - Paint paint = new Paint(); - paint.setAntiAlias(true); - paint.setDither(true); - paint.setColor(mColor); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeJoin(Paint.Join.ROUND); - paint.setStrokeCap(Paint.Cap.ROUND); - paint.setStrokeWidth(2); - c.drawPath(path, paint); - return bitmap; - } - - /** - * save the gesture as XML - * @param namespace - * @param serializer - * @throws IOException - */ - public void toXML(String namespace, XmlSerializer serializer) throws IOException { - serializer.startTag(namespace, "stroke"); - serializer.attribute(namespace, "timestamp", Long.toString(mTimestamp)); - serializer.attribute(namespace, "id", Long.toString(mID)); - serializer.attribute(namespace, "color", Integer.toString(mColor)); - serializer.attribute(namespace, "width", Float.toString(mWidth)); - Iterator it = this.mPtsBuffer.iterator(); - String pts = ""; - while (it.hasNext()) { - PointF fp = (PointF)it.next(); - if (pts.length() > 0) - pts += ","; - pts += fp.x + "," + fp.y; - } - serializer.text(pts); - serializer.endTag(namespace, "stroke"); - } - - - public void createFromString(String str) { - StringTokenizer st = new StringTokenizer(str, "#"); - - String para = st.nextToken(); - StringTokenizer innerst = new StringTokenizer(para, ","); - this.mBBX = new RectF(); - this.mBBX.left = Float.parseFloat(innerst.nextToken()); - this.mBBX.top = Float.parseFloat(innerst.nextToken()); - this.mBBX.right = Float.parseFloat(innerst.nextToken()); - this.mBBX.bottom = Float.parseFloat(innerst.nextToken()); - - para = st.nextToken(); - innerst = new StringTokenizer(para, ","); - while (innerst.hasMoreTokens()) { - String s = innerst.nextToken().trim(); - if (s.length()==0) - break; - float x = Float.parseFloat(s); - float y = Float.parseFloat(innerst.nextToken()); - this.mPtsBuffer.add(new PointF(x, y)); - } - - para = st.nextToken(); - this.mColor = Integer.parseInt(para); - - para = st.nextToken(); - this.mWidth = Float.parseFloat(para); - - para = st.nextToken(); - this.mLength = Float.parseFloat(para); - - para = st.nextToken(); - this.mTimestamp = Long.parseLong(para); - } - - @Override - public String toString() { - String str = ""; - - str += "#" + this.mBBX.left + "," + this.mBBX.top + "," + - this.mBBX.right + "," + this.mBBX.bottom; - - str += "#"; - Iterator<PointF> it = this.mPtsBuffer.iterator(); - while (it.hasNext()) { - PointF fp = it.next(); - str += fp.x + "," + fp.y + ","; - } - - str += "#"; - str += this.mColor; - - str += "#"; - str += this.mWidth; - - str += "#"; - str += this.mLength; - - str += "#"; - str += this.mTimestamp; - - return str; - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - public Gesture createFromParcel(Parcel in) { - String str = in.readString(); - Gesture stk = new Gesture(); - stk.createFromString(str); - return stk; - } - - public Gesture[] newArray(int size) { - return new Gesture[size]; - } - }; - - public static Gesture buildFromArray(byte[] bytes) { - String str = new String(bytes); - Gesture stk = new Gesture(); - stk.createFromString(str); - return stk; - } - - public static byte[] saveToArray(Gesture stk) { - String str = stk.toString(); - return str.getBytes(); - } - - public void writeToParcel(Parcel out, int flags) { - out.writeString(this.toString()); - } - - public int describeContents() { - return CONTENTS_FILE_DESCRIPTOR; - } -} diff --git a/tests/sketch/src/com/android/gesture/GestureLib.java b/tests/sketch/src/com/android/gesture/GestureLib.java deleted file mode 100755 index d0a25f2..0000000 --- a/tests/sketch/src/com/android/gesture/GestureLib.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * 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 com.android.gesture; - -import android.util.Log; -import android.util.Xml; -import android.util.Xml.Encoding; - -import com.android.gesture.recognizer.Classifier; -import com.android.gesture.recognizer.Instance; -import com.android.gesture.recognizer.NearestNeighbor; -import com.android.gesture.recognizer.Prediction; - -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; -import org.xmlpull.v1.XmlSerializer; - -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.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Set; -import java.util.StringTokenizer; - -public class GestureLib { - - private static final String LOGTAG = "GestureLib"; - private static String namespace = "ink"; - private final String datapath; - private HashMap<String, ArrayList<Gesture>> name2gestures = - new HashMap<String, ArrayList<Gesture>>(); - private Classifier mClassifier; - - public GestureLib(String path) { - datapath = path; - mClassifier = new NearestNeighbor(); - } - - public Classifier getClassifier() { - return mClassifier; - } - - /** - * get all the labels in the library - * @return a set of strings - */ - public Set<String> getLabels() { - return name2gestures.keySet(); - } - - public ArrayList<Prediction> recognize(Gesture gesture) { - Instance instance = Instance.createInstance(gesture, null); - return mClassifier.classify(instance); - } - - public void addGesture(String name, Gesture gesture) { - Log.v(LOGTAG, "add an example for gesture: " + name); - ArrayList<Gesture> gestures = name2gestures.get(name); - if (gestures == null) { - gestures = new ArrayList<Gesture>(); - name2gestures.put(name, gestures); - } - gestures.add(gesture); - mClassifier.addInstance( - Instance.createInstance(gesture, name)); - } - - public void removeGesture(String name, Gesture gesture) { - ArrayList<Gesture> gestures = name2gestures.get(name); - if (gestures == null) { - return; - } - - gestures.remove(gesture); - - // if there are no more samples, remove the entry automatically - if (gestures.isEmpty()) { - name2gestures.remove(name); - } - - mClassifier.removeInstance(gesture.getID()); - } - - public ArrayList<Gesture> getGestures(String label) { - ArrayList<Gesture> gestures = name2gestures.get(label); - if (gestures != null) - return (ArrayList<Gesture>)gestures.clone(); - else - return null; - } - - public void load() { - String filename = datapath - + File.separator + "gestures.xml"; - File f = new File(filename); - if (f.exists()) { - try { - loadInk(filename, null); - } - catch (SAXException ex) { - ex.printStackTrace(); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - } - - public void save() { - try { - compactSave(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private void compactSave() throws IOException { - File f = new File(datapath); - if (f.exists() == false) { - f.mkdirs(); - } - String filename = datapath + File.separator + "gestures.xml"; - Log.v(LOGTAG, "save to " + filename); - BufferedOutputStream fos = new BufferedOutputStream( - new FileOutputStream(filename)); - - PrintWriter writer = new PrintWriter(fos); - XmlSerializer serializer = Xml.newSerializer(); - serializer.setOutput(writer); - serializer.startDocument(Encoding.ISO_8859_1.name(), null); - serializer.startTag(namespace, "gestures"); - Iterator<String> it = name2gestures.keySet().iterator(); - while (it.hasNext()) { - String key = it.next(); - ArrayList<Gesture> gestures = name2gestures.get(key); - saveGestures(serializer, key, gestures); - } - - serializer.endTag(namespace, "gestures"); - serializer.endDocument(); - serializer.flush(); - writer.close(); - fos.close(); - } - - private static void saveGestures(XmlSerializer serializer, - String name, ArrayList<Gesture> strokes) throws IOException { - serializer.startTag(namespace, "gesture"); - serializer.startTag(namespace, "name"); - serializer.text(name); - serializer.endTag(namespace, "name"); - Iterator<Gesture> it = strokes.iterator(); - while (it.hasNext()) { - Gesture stk = it.next(); - stk.toXML(namespace, serializer); - } - serializer.endTag(namespace, "gesture"); - } - - private void loadInk(String filename, String label) throws SAXException, IOException { - Log.v(LOGTAG, "load from " + filename); - BufferedInputStream in = new BufferedInputStream( - new FileInputStream(filename)); - Xml.parse(in, Encoding.ISO_8859_1, new CompactInkHandler()); - in.close(); - } - - class CompactInkHandler implements ContentHandler { - - Gesture currentGesture = null; - StringBuffer buffer = null; - String gestureName; - ArrayList<Gesture> gestures; - - CompactInkHandler() { - } - - // Receive notification of character data. - public void characters(char[] ch, int start, int length) { - buffer.append(ch, start, length); - } - - //Receive notification of the end of a document. - public void endDocument() { - } - - // Receive notification of the end of an element. - public void endElement(String uri, String localName, String qName) { - if (localName.equals("gesture")) { - name2gestures.put(gestureName, gestures); - gestures = null; - } else if (localName.equals("name")) { - gestureName = buffer.toString(); - } else if (localName.equals("stroke")) { - StringTokenizer tokenizer = new StringTokenizer(buffer.toString(), ","); - while (tokenizer.hasMoreTokens()) { - String str = tokenizer.nextToken(); - float x = Float.parseFloat(str); - str = tokenizer.nextToken(); - float y = Float.parseFloat(str); - try - { - currentGesture.addPoint(x, y); - } - catch(Exception ex) { - ex.printStackTrace(); - } - } - gestures.add(currentGesture); - mClassifier.addInstance( - Instance.createInstance(currentGesture, gestureName)); - currentGesture = null; - } - } - - // End the scope of a prefix-URI mapping. - public void endPrefixMapping(String prefix) { - } - - //Receive notification of ignorable whitespace in element content. - public void ignorableWhitespace(char[] ch, int start, int length) { - } - - //Receive notification of a processing instruction. - public void processingInstruction(String target, String data) { - } - - // Receive an object for locating the origin of SAX document events. - public void setDocumentLocator(Locator locator) { - } - - // Receive notification of a skipped entity. - public void skippedEntity(String name) { - } - - // Receive notification of the beginning of a document. - public void startDocument() { - } - - // Receive notification of the beginning of an element. - public void startElement(String uri, String localName, String qName, Attributes atts) { - if (localName.equals("gesture")) { - gestures = new ArrayList<Gesture>(); - } else if (localName.equals("name")) { - buffer = new StringBuffer(); - } else if (localName.equals("stroke")) { - currentGesture = new Gesture(); - currentGesture.setTimestamp(Long.parseLong(atts.getValue(namespace, "timestamp"))); - currentGesture.setColor(Integer.parseInt(atts.getValue(namespace, "color"))); - currentGesture.setStrokeWidth(Float.parseFloat(atts.getValue(namespace, "width"))); - buffer = new StringBuffer(); - } - } - - public void startPrefixMapping(String prefix, String uri) { - } - } -} diff --git a/tests/sketch/src/com/android/gesture/GesturePad.java b/tests/sketch/src/com/android/gesture/GesturePad.java deleted file mode 100755 index 45a09e6..0000000 --- a/tests/sketch/src/com/android/gesture/GesturePad.java +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (C) 2008 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 com.android.gesture; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.PointF; -import android.os.Handler; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import java.util.ArrayList; -import java.util.Iterator; - -/** - * A view for rendering and processing gestures - */ - -public class GesturePad extends View { - - public static final float TOUCH_TOLERANCE = 4; - public static final int default_foreground = Color.argb(255, 255, 255, 0); - private int background = Color.argb(0, 0, 0, 0); - private int foreground = default_foreground; - private int uncertain_foreground = Color.argb(55, 255, 255, 0); - private Bitmap mBitmap; - private Canvas mCanvas; - private Path mPath; - private Paint mBitmapPaint; - private Paint mPaint; - private Paint mDebugPaint; - private float mX, mY; - private boolean mEnableInput = true; - private boolean mEnableRendering = true; - private boolean mCacheGesture = true; - private Gesture mCurrentGesture = null; - ArrayList<GestureListener> mGestureListeners = new ArrayList<GestureListener>(); - - private boolean mShouldFadingOut = true; - private boolean mIsFadingOut = false; - private float mFadingAlpha = 1; - - private boolean reconstruct = false; - - private ArrayList<Path> debug = new ArrayList<Path>(); - private Handler mHandler = new Handler(); - - private Runnable mFadingOut = new Runnable() { - public void run() { - mFadingAlpha -= 0.03f; - if (mFadingAlpha <= 0) { - mIsFadingOut = false; - mPath.reset(); - } else { - mHandler.postDelayed(this, 100); - } - invalidate(); - } - }; - - public GesturePad(Context context) { - super(context); - init(); - } - - public GesturePad(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public boolean isEnableRendering() { - return this.mEnableRendering; - } - - public Gesture getCurrentGesture() { - return mCurrentGesture; - } - - public Paint getPaint() { - return mPaint; - } - - public void setColor(int c) { - this.foreground = c; - } - - public void setFadingAlpha(float f) { - mFadingAlpha = f; - } - - public void setCurrentGesture(Gesture stk) { - this.mCurrentGesture = stk; - reconstruct = true; - } - - private void init() { - mDebugPaint = new Paint(); - mDebugPaint.setColor(Color.WHITE); - mDebugPaint.setStrokeWidth(4); - mDebugPaint.setAntiAlias(true); - mDebugPaint.setStyle(Paint.Style.STROKE); - - mPaint = new Paint(); - mPaint.setAntiAlias(true); - mPaint.setDither(true); - mPaint.setColor(foreground); - mPaint.setStyle(Paint.Style.STROKE); - mPaint.setStrokeJoin(Paint.Join.ROUND); - mPaint.setStrokeCap(Paint.Cap.ROUND); - mPaint.setStrokeWidth(12); - - mBitmapPaint = new Paint(Paint.DITHER_FLAG); - mPath = new Path(); - - reconstruct = false; - } - - public void cacheGesture(boolean b) { - mCacheGesture = b; - } - - public void enableRendering(boolean b) { - mEnableRendering = b; - } - - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - // TODO Auto-generated method stub - super.onSizeChanged(w, h, oldw, oldh); - - if (w <=0 || h <=0) - return; - - int width = w>oldw? w : oldw; - int height = h>oldh? h : oldh; - Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - mCanvas = new Canvas(newBitmap); - - if (mBitmap != null) { - mCanvas.drawColor(background); - mCanvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); - mCanvas.drawPath(mPath, mPaint); - } - - mBitmap = newBitmap; - } - - public void addGestureListener(GestureListener l) { - this.mGestureListeners.add(l); - } - - public void removeGestureListener(GestureListener l) { - this.mGestureListeners.remove(l); - } - - @Override - protected void onDraw(Canvas canvas) { - canvas.drawColor(background); - - if (mCacheGesture) - canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); - - if (mIsFadingOut) { - int color = foreground; - int alpha = (int)(Color.alpha(color) * mFadingAlpha); - mPaint.setColor(Color.argb(alpha, - Color.red(color), - Color.green(color), - Color.blue(color))); - } else if (mEnableRendering == false) { - mPaint.setColor(uncertain_foreground); - } else { - mPaint.setColor(foreground); - } - - if (reconstruct) { - - if (this.mCurrentGesture != null) { - float xedge = 30; - float yedge = 30; - float w = this.getWidth() - 2 * xedge; - float h = this.getHeight() - 2 * yedge; - float sx = w / this.mCurrentGesture.getBBX().width(); - float sy = h / mCurrentGesture.getBBX().height(); - float scale = sx>sy?sy:sx; - convertFromStroke(mCurrentGesture); - Matrix matrix = new Matrix(); - matrix.preTranslate(-mCurrentGesture.getBBX().centerX(), -mCurrentGesture.getBBX().centerY()); - matrix.postScale(scale, scale); - matrix.postTranslate(this.getWidth()/2, this.getHeight()/2); - this.mPath.transform(matrix); - } else { - mPath.reset(); - } - - reconstruct = false; - } - - canvas.drawPath(mPath, mPaint); - - Iterator<Path> it = debug.iterator(); - while (it.hasNext()) { - Path path = it.next(); - canvas.drawPath(path, mDebugPaint); - } - } - - public void clearDebugPath() { - debug.clear(); - } - - public void addDebugPath(Path path) { - debug.add(path); - } - - public void addDebugPath(ArrayList<Path> paths) { - debug.addAll(paths); - } - - public void clear() { - mPath = new Path(); - this.mCurrentGesture = null; - mCanvas.drawColor(background); - this.invalidate(); - } - - private void convertFromStroke(Gesture stk) { - mPath = null; - Iterator it = stk.getPoints().iterator(); - while (it.hasNext()) { - PointF p = (PointF) it.next(); - if (mPath == null) { - mPath = new Path(); - mPath.moveTo(p.x, p.y); - mX = p.x; - mY = p.y; - } else { - float dx = Math.abs(p.x - mX); - float dy = Math.abs(p.y - mY); - if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { - mPath.quadTo(mX, mY, (p.x + mX)/2, (p.y + mY)/2); - mX = p.x; - mY = p.y; - } - } - } - mPath.lineTo(mX, mY); - } - - public void setEnableInput(boolean b) { - mEnableInput = b; - } - - public boolean isEnableInput() { - return mEnableInput; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - - if(mEnableInput == false) - return true; - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - touch_start(event); - invalidate(); - break; - case MotionEvent.ACTION_MOVE: - touch_move(event); - invalidate(); - break; - case MotionEvent.ACTION_UP: - touch_up(event); - invalidate(); - break; - } - return true; - } - - private void touch_start(MotionEvent event) { - mIsFadingOut = false; - mHandler.removeCallbacks(mFadingOut); - - float x = event.getX(); - float y = event.getY(); - - mCurrentGesture = new Gesture(); - mCurrentGesture.addPoint(x, y); - - mPath.reset(); - mPath.moveTo(x, y); - mX = x; - mY = y; - - Iterator<GestureListener> it = mGestureListeners.iterator(); - while (it.hasNext()) { - it.next().onStartGesture(this, event); - } - } - - private void touch_move(MotionEvent event) { - float x = event.getX(); - float y = event.getY(); - - float dx = Math.abs(x - mX); - float dy = Math.abs(y - mY); - if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { - mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2); - mX = x; - mY = y; - } - - mCurrentGesture.addPoint(x, y); - - Iterator<GestureListener> it = mGestureListeners.iterator(); - while (it.hasNext()) { - it.next().onGesture(this, event); - } - } - - public void setFadingOut(boolean b) { - mShouldFadingOut = b; - mIsFadingOut = false; - } - - public boolean shouldFadingOut() { - return mShouldFadingOut; - } - - private void touch_up(MotionEvent event) { - mPath.lineTo(mX, mY); - - if (mCacheGesture) - mCanvas.drawPath(mPath, mPaint); - - // kill this so we don't double draw - if (shouldFadingOut()) { - mFadingAlpha = 1; - mIsFadingOut = true; - mHandler.removeCallbacks(mFadingOut); - mHandler.postDelayed(mFadingOut, 100); - } - - Iterator<GestureListener> it = mGestureListeners.iterator(); - while (it.hasNext()) { - it.next().onFinishGesture(this, event); - } - } - -} diff --git a/tests/sketch/src/com/android/gesture/example/ContactAdapter.java b/tests/sketch/src/com/android/gesture/example/ContactAdapter.java new file mode 100644 index 0000000..008a972 --- /dev/null +++ b/tests/sketch/src/com/android/gesture/example/ContactAdapter.java @@ -0,0 +1,100 @@ +/* + * 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 com.android.gesture.example; + +import android.app.Activity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import java.util.ArrayList; + +class ContactAdapter extends ArrayAdapter<ContactItem> { + + private LayoutInflater mInflater; + + public ContactAdapter(Activity activity, ArrayList<ContactItem> contacts) { + super(activity, 0, contacts); + mInflater = activity.getLayoutInflater(); + } + + @Override + public ContactItem getItem(int position) { + return super.getItem(position); + } + + @Override + public long getItemId(int position) { + return getItem(position).itemID; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + final ContactItem info = getItem(position); + + View view = convertView; + if (view == null) { + view = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false); + view.setTag(view.findViewById(android.R.id.text1)); + } + + final TextView textView = (TextView)view.getTag(); + textView.setText(info.toString()); + + return view; + } + + public int search(String query) { + if (query != null && query.length() > 0) { + int start = 0; + int end = getCount() - 1; + int index = binarySearch(query, start, end); + for (index = index - 1; index >= 0; index--) { + String str = getItem(index).toString().toLowerCase(); + if (!str.startsWith(query)) { + return index + 1; + } + if (index == 0) { + return 0; + } + } + return -1; + } else { + return -1; + } + } + + private int binarySearch(String prefix, int start, int end) { + if (start > end) { + return -1; + } + int mid = (start + end) / 2; + String str = getItem(mid).toString().toLowerCase(); + if (prefix.compareTo(str) <= 0) { + if (str.startsWith(prefix)) { + return mid; + } else { + return binarySearch(prefix, start, mid - 1); + } + } else { + return binarySearch(prefix, mid + 1, end); + } + } + +} diff --git a/tests/sketch/src/com/android/gesture/GestureListener.java b/tests/sketch/src/com/android/gesture/example/ContactItem.java index ebb4149..557c4d9 100755..100644 --- a/tests/sketch/src/com/android/gesture/GestureListener.java +++ b/tests/sketch/src/com/android/gesture/example/ContactItem.java @@ -14,12 +14,21 @@ * limitations under the License. */ -package com.android.gesture; +package com.android.gesture.example; -import android.view.MotionEvent; -public interface GestureListener { - public void onStartGesture(GesturePad pad, MotionEvent event); - public void onGesture(GesturePad pad, MotionEvent event); - public void onFinishGesture(GesturePad pad, MotionEvent event); +class ContactItem { + final String itemName; + + final long itemID; + + public ContactItem(long id, String name) { + itemID = id; + itemName = name; + } + + @Override + public String toString() { + return itemName; + } } diff --git a/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java b/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java new file mode 100644 index 0000000..eda4224 --- /dev/null +++ b/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java @@ -0,0 +1,119 @@ +/* + * 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 com.android.gesture.example; + +import android.app.Activity; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.Intent; +import android.database.Cursor; +import android.os.Bundle; +import android.provider.Contacts.People; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ListView; + +import android.gesture.Gesture; +import android.gesture.GestureOverlayView; +import android.gesture.LetterRecognizer; +import android.gesture.Prediction; +import android.gesture.TouchThroughGestureListener; + +import java.util.ArrayList; + +public class ContactListGestureOverlay extends Activity { + + private static final String LOGTAG = "ContactListGestureOverlay"; + + private static final String SORT_ORDER = People.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; + + private static final String[] CONTACTS_PROJECTION = new String[] { + People._ID, // 0 + People.DISPLAY_NAME, // 1 + }; + + private ContactAdapter mContactAdapter; + + private TouchThroughGestureListener mGestureProcessor; + + private LetterRecognizer mRecognizer; + + private ListView mContactList; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); + setContentView(R.layout.overlaydemo); + + setProgressBarIndeterminateVisibility(true); + + // create a letter recognizer + mRecognizer = LetterRecognizer.getLetterRecognizer(this, LetterRecognizer.RECOGNIZER_LATIN_LOWERCASE); + + // load the contact list + mContactList = (ListView) findViewById(R.id.list); + registerForContextMenu(mContactList); + mContactList.setTextFilterEnabled(true); + mContactList.setOnItemClickListener(new AdapterView.OnItemClickListener() { + public void onItemClick(AdapterView<?> parent, View v, int position, long id) { + if (!mGestureProcessor.isGesturing()) { + Intent intent = new Intent(Intent.ACTION_VIEW, ContentUris.withAppendedId( + People.CONTENT_URI, id)); + startActivity(intent); + } + } + }); + ContentResolver resolver = getContentResolver(); + Cursor cursor = resolver.query(People.CONTENT_URI, CONTACTS_PROJECTION, null, null, + SORT_ORDER); + ArrayList<ContactItem> list = new ArrayList<ContactItem>(); + while (cursor.moveToNext()) { + list.add(new ContactItem(cursor.getLong(0), cursor.getString(1))); + } + mContactAdapter = new ContactAdapter(this, list); + mContactList.setAdapter(mContactAdapter); + + setProgressBarIndeterminateVisibility(false); + + // add a gesture overlay on top of the ListView + GestureOverlayView overlay = new GestureOverlayView(this); + mGestureProcessor = new TouchThroughGestureListener(mContactList); + mGestureProcessor.setGestureType(TouchThroughGestureListener.MULTIPLE_STROKE); + mGestureProcessor.addOnGestureActionListener(new TouchThroughGestureListener.OnGesturePerformedListener() { + public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) { + ArrayList<Prediction> predictions = mRecognizer.recognize(gesture); + if (!predictions.isEmpty()) { + Log.v(LOGTAG, "1st Prediction : " + predictions.get(0).name); + Log.v(LOGTAG, "2nd Prediction : " + predictions.get(1).name); + Log.v(LOGTAG, "3rd Prediction : " + predictions.get(2).name); + int index = mContactAdapter.search(predictions.get(0).name); + if (index != -1) { + mContactList.setSelection(index); + } + } + } + }); + overlay.addOnGestureListener(mGestureProcessor); + ViewGroup.LayoutParams params = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT); + this.addContentView(overlay, params); + } +} diff --git a/tests/sketch/src/com/android/gesture/example/GestureEntry.java b/tests/sketch/src/com/android/gesture/example/GestureEntry.java new file mode 100644 index 0000000..200f89f --- /dev/null +++ b/tests/sketch/src/com/android/gesture/example/GestureEntry.java @@ -0,0 +1,206 @@ +/* + * 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 com.android.gesture.example; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.os.Environment; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.Spinner; +import android.widget.AdapterView.OnItemSelectedListener; +import android.gesture.Gesture; + +import android.gesture.GestureLibrary; +import android.gesture.GestureOverlayView; +import android.gesture.Prediction; + +import java.io.File; +import java.util.ArrayList; + +public class GestureEntry extends Activity { + + private static final String PARCEL_KEY = "gesture"; + + static final String GESTURE_FILE_NAME = Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + "demo_library.gestures"; + + private static final int DIALOG_NEW_ENTRY = 1; + + private static final int NEW_ID = Menu.FIRST; + + private static final int VIEW_ID = Menu.FIRST + 1; + + private GestureOverlayView mGesturePad; + + private Spinner mRecognitionResult; + + private GestureLibrary mGestureLibrary; + + private boolean mChangedByRecognizer = false; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.demo); + + // init the gesture library + mGestureLibrary = new GestureLibrary(GESTURE_FILE_NAME); + mGestureLibrary.load(); + + // create the spinner for showing the recognition results + // the spinner also allows a user to correct a prediction + mRecognitionResult = (Spinner) findViewById(R.id.spinner); + mRecognitionResult.setOnItemSelectedListener(new OnItemSelectedListener() { + + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + // correct the recognition result by adding the new example + if (!mChangedByRecognizer) { + mGestureLibrary.addGesture(parent.getSelectedItem().toString(), mGesturePad + .getCurrentGesture()); + } else { + mChangedByRecognizer = false; + } + } + + public void onNothingSelected(AdapterView<?> parent) { + + } + + }); + + // create the area for drawing a gesture + mGesturePad = (GestureOverlayView) findViewById(R.id.drawingpad); + mGesturePad.setBackgroundColor(Color.BLACK); + mGesturePad.addOnGestureListener(new GestureOverlayView.OnGestureListener() { + public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) { + recognize(overlay.getCurrentGesture()); + } + + public void onGesture(GestureOverlayView overlay, MotionEvent event) { + } + + public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) { + overlay.clear(false); + } + }); + + if (savedInstanceState != null) { + Gesture gesture = (Gesture) savedInstanceState.getParcelable(PARCEL_KEY); + if (gesture != null) { + mGesturePad.setCurrentGesture(gesture); + } + } + } + + @Override + protected Dialog onCreateDialog(int id) { + LayoutInflater factory = LayoutInflater.from(this); + final View textEntryView = factory.inflate(R.layout.newgesture_dialog, null); + return new AlertDialog.Builder(GestureEntry.this).setTitle( + R.string.newgesture_text_entry).setView(textEntryView).setPositiveButton( + R.string.newgesture_dialog_ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + EditText edittext = (EditText) ((AlertDialog) dialog) + .findViewById(R.id.gesturename_edit); + String text = edittext.getText().toString().trim(); + if (text.length() > 0) { + mGestureLibrary.addGesture(text, mGesturePad.getCurrentGesture()); + } + } + }).setNegativeButton(R.string.newgesture_dialog_cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + } + }).create(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + menu.add(0, NEW_ID, 0, R.string.newgesture).setShortcut('0', 'n').setIcon( + android.R.drawable.ic_menu_add); + menu.add(0, VIEW_ID, 0, R.string.viewgesture).setShortcut('1', 'v').setIcon( + android.R.drawable.ic_menu_view); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case NEW_ID: + if (mGesturePad.getCurrentGesture() != null) { + showDialog(DIALOG_NEW_ENTRY); + } + break; + + case VIEW_ID: + startActivityForResult(new Intent(this, GestureLibViewer.class), VIEW_ID); + break; + } + + return super.onOptionsItemSelected(item); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + mGestureLibrary.load(); + mGesturePad.clear(false); + } + + @Override + protected void onPause() { + super.onPause(); + mGestureLibrary.save(); + } + + @Override + protected void onPrepareDialog(int id, Dialog dialog) { + super.onPrepareDialog(id, dialog); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + Gesture gesture = mGesturePad.getCurrentGesture(); + if (gesture != null) { + outState.putParcelable(PARCEL_KEY, gesture); + } + mGestureLibrary.save(); + } + + private void recognize(Gesture gesture) { + mChangedByRecognizer = true; + ArrayList<Prediction> predictions = mGestureLibrary.recognize(gesture); + ArrayAdapter<Prediction> adapter = new ArrayAdapter<Prediction>(this, + android.R.layout.simple_spinner_item, predictions); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mRecognitionResult.setAdapter(adapter); + } + +} diff --git a/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java b/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java deleted file mode 100755 index 8fee21a..0000000 --- a/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (C) 2008 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 com.android.gesture.example; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.EditText; -import android.widget.Spinner; -import android.widget.AdapterView.OnItemSelectedListener; - -import com.android.gesture.Gesture; -import com.android.gesture.GestureLib; -import com.android.gesture.GestureListener; -import com.android.gesture.GesturePad; -import com.android.gesture.R; -import com.android.gesture.recognizer.Prediction; - -import java.util.ArrayList; - -/** - * The demo shows how to construct a gesture-based user interface on Android. - */ - -public class GestureEntryDemo extends Activity { - - private static final int DIALOG_NEW_ENTRY = 1; - private static final int NEW_ID = Menu.FIRST; - private static final int VIEW_ID = Menu.FIRST + 1; - - GesturePad mView; - Spinner mResult; - GestureLib mRecognizer; - boolean mChangedByRecognizer = false; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.demo); - - // init the recognizer - mRecognizer = new GestureLib("/sdcard/gestureentry"); - mRecognizer.load(); - - // create the spinner for showing the recognition results - // the spinner also allows a user to correct a prediction - mResult = (Spinner) findViewById(R.id.spinner); - mResult.setOnItemSelectedListener(new OnItemSelectedListener() { - - public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - // TODO Auto-generated method stub - // correct the recognition result by adding the new example - if (mChangedByRecognizer == false) { - mRecognizer.addGesture(parent.getSelectedItem().toString(), - mView.getCurrentGesture()); - } else { - mChangedByRecognizer = false; - } - } - - public void onNothingSelected(AdapterView<?> parent) { - // TODO Auto-generated method stub - - } - - }); - - // create the area for drawing a gesture - mView = (GesturePad)this.findViewById(R.id.drawingpad); - mView.cacheGesture(false); - mView.setFadingOut(false); - mView.addGestureListener(new GestureListener() { - public void onFinishGesture(GesturePad patch, MotionEvent event) { - // TODO Auto-generated method stub - recognize(patch.getCurrentGesture()); - } - public void onGesture(GesturePad patch, MotionEvent event) { - // TODO Auto-generated method stub - - } - public void onStartGesture(GesturePad patch, MotionEvent event) { - // TODO Auto-generated method stub - - } - }); - - - if (savedInstanceState != null) { - mView.setCurrentGesture( - (Gesture)savedInstanceState.getParcelable("gesture")); - } - } - - @Override - protected Dialog onCreateDialog(int id) { - // create the dialog for adding a new entry - LayoutInflater factory = LayoutInflater.from(this); - final View textEntryView = - factory.inflate(R.layout.newgesture_dialog, null); - return new AlertDialog.Builder(GestureEntryDemo.this) - .setTitle(R.string.newgesture_text_entry) - .setView(textEntryView) - .setPositiveButton(R.string.newgesture_dialog_ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - /* User clicked OK so do some stuff */ - EditText edittext = - (EditText)((AlertDialog)dialog).findViewById(R.id.gesturename_edit); - String text = edittext.getText().toString().trim(); - if (text.length() > 0) { - mRecognizer.addGesture(text, mView.getCurrentGesture()); - } - } - }) - .setNegativeButton(R.string.newgesture_dialog_cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - /* User clicked cancel so do some stuff */ - } - }) - .create(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - // TODO Auto-generated method stub - super.onCreateOptionsMenu(menu); - menu.add(0, NEW_ID, 0, R.string.newgesture) - .setShortcut('0', 'n') - .setIcon(android.R.drawable.ic_menu_add); - menu.add(0, VIEW_ID, 0, R.string.viewgesture) - .setShortcut('1', 'v') - .setIcon(android.R.drawable.ic_menu_view); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - // Handle all of the possible menu actions. - switch (item.getItemId()) { - case NEW_ID: - // if there has been a gesture on the canvas - if (mView.getCurrentGesture() != null) { - showDialog(DIALOG_NEW_ENTRY); - } - break; - - case VIEW_ID: - startActivityForResult( - new Intent(this, GestureLibViewer.class), VIEW_ID); - break; - } - - return super.onOptionsItemSelected(item); - } - - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - mRecognizer.load(); - mView.clear(); - } - - @Override - protected void onPause() { - // TODO Auto-generated method stub - super.onPause(); - mRecognizer.save(); - } - - - @Override - protected void onPrepareDialog(int id, Dialog dialog) { - // TODO Auto-generated method stub - super.onPrepareDialog(id, dialog); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - // TODO Auto-generated method stub - super.onSaveInstanceState(outState); - outState.putParcelable("gesture", mView.getCurrentGesture()); - mRecognizer.save(); - } - - public void recognize(Gesture ink) { - mChangedByRecognizer = true; - ArrayList<Prediction> predictions = mRecognizer.recognize(ink); - ArrayAdapter adapter = new ArrayAdapter(this, - android.R.layout.simple_spinner_item, predictions); - adapter.setDropDownViewResource( - android.R.layout.simple_spinner_dropdown_item); - mResult.setAdapter(adapter); - } - -} diff --git a/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java index 7ae7fc5..aa07e7b 100755 --- a/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java +++ b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * 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. @@ -17,8 +17,6 @@ package com.android.gesture.example; import android.app.Activity; -import android.graphics.Matrix; -import android.graphics.Path; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; @@ -28,230 +26,158 @@ import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.Spinner; import android.widget.AdapterView.OnItemSelectedListener; +import android.gesture.Gesture; -import com.android.gesture.Gesture; -import com.android.gesture.GestureLib; -import com.android.gesture.GesturePad; -import com.android.gesture.R; -import com.android.gesture.recognizer.Instance; +import android.gesture.GestureLibrary; +import android.gesture.GestureOverlayView; import java.util.ArrayList; import java.util.Collections; /** - * GestureLibViewer is for viewing existing gestures and + * GestureLibViewer gives an example on how to browse existing gestures and * removing unwanted gestures. */ -public class GestureLibViewer extends Activity { - - GesturePad mView; - Spinner mResult; - GestureLib mRecognizer; - ArrayList<Gesture> mSamples; - int mCurrentGestureIndex; +public class GestureLibViewer extends Activity { + + private GestureOverlayView mGesturePad; + + private Spinner mGestureCategory; + + private GestureLibrary mGesureLibrary; + + private ArrayList<Gesture> mGestures; + + private int mCurrentGestureIndex; + + private class RemoveGestureListener implements OnClickListener { + public void onClick(View v) { + if (mGestures.isEmpty()) { + return; + } + + String name = (String) mGestureCategory.getSelectedItem(); + Gesture gesture = mGestures.get(mCurrentGestureIndex); + mGesureLibrary.removeGesture(name, gesture); + + mGestures = mGesureLibrary.getGestures(name); + + if (mGestures == null) { + // delete the entire entry + mCurrentGestureIndex = 0; + ArrayList<String> list = new ArrayList<String>(); + list.addAll(mGesureLibrary.getGestureEntries()); + Collections.sort(list); + ArrayAdapter<String> adapter = new ArrayAdapter<String>(GestureLibViewer.this, + android.R.layout.simple_spinner_item, list); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mGestureCategory.setAdapter(adapter); + } else { + if (mCurrentGestureIndex > mGestures.size() - 1) { + mCurrentGestureIndex--; + } + gesture = mGestures.get(mCurrentGestureIndex); + mGesturePad.setCurrentGesture(gesture); + mGesturePad.invalidate(); + } + } + } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gestureviewer); - - // create the area for drawing a glyph - mView = (GesturePad)this.findViewById(R.id.drawingpad); - mView.cacheGesture(false); - mView.setFadingOut(false); - mView.setEnableInput(false); - - // init the recognizer - mRecognizer = new GestureLib("/sdcard/gestureentry"); - mRecognizer.load(); - mResult = (Spinner) findViewById(R.id.spinner); + // create the area for drawing a gesture + mGesturePad = (GestureOverlayView) findViewById(R.id.drawingpad); + mGesturePad.setEnabled(false); + + // init the gesture library + mGesureLibrary = new GestureLibrary(GestureEntry.GESTURE_FILE_NAME); + mGesureLibrary.load(); + + mGestureCategory = (Spinner) findViewById(R.id.spinner); ArrayList<String> list = new ArrayList<String>(); - list.addAll(mRecognizer.getLabels()); - Collections.sort(list); - ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, - android.R.layout.simple_spinner_item, - list); - adapter.setDropDownViewResource( - android.R.layout.simple_spinner_dropdown_item); - mResult.setAdapter(adapter); - mSamples = mRecognizer.getGestures(list.get(0)); - if (mSamples.isEmpty() == false) { + if (!mGesureLibrary.getGestureEntries().isEmpty()) { + list.addAll(mGesureLibrary.getGestureEntries()); + Collections.sort(list); + ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, + android.R.layout.simple_spinner_item, list); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mGestureCategory.setAdapter(adapter); + mGestures = mGesureLibrary.getGestures(list.get(0)); mCurrentGestureIndex = 0; - Gesture gesture = mSamples.get(mCurrentGestureIndex); - mView.setCurrentGesture(gesture); - mView.clearDebugPath(); - mView.addDebugPath( - toPath(mRecognizer.getClassifier().getInstance(gesture.getID()))); + Gesture gesture = mGestures.get(mCurrentGestureIndex); + mGesturePad.setCurrentGesture(gesture); } - - mResult.setOnItemSelectedListener(new OnItemSelectedListener() { + + mGestureCategory.setOnItemSelectedListener(new OnItemSelectedListener() { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - // TODO Auto-generated method stub - mSamples = mRecognizer.getGestures( - (String)mResult.getSelectedItem()); - if (mSamples.isEmpty() == false) { + mGestures = mGesureLibrary.getGestures((String) mGestureCategory.getSelectedItem()); + if (!mGestures.isEmpty()) { mCurrentGestureIndex = 0; - Gesture gesture = mSamples.get(mCurrentGestureIndex); - mView.setCurrentGesture(gesture); - mView.clearDebugPath(); - mView.addDebugPath( - toPath(mRecognizer.getClassifier().getInstance(gesture.getID()))); + Gesture gesture = mGestures.get(mCurrentGestureIndex); + mGesturePad.setCurrentGesture(gesture); } - mView.invalidate(); + mGesturePad.invalidate(); } - + public void onNothingSelected(AdapterView<?> parent) { - // TODO Auto-generated method stub - - } - - }); - - Button remove = (Button)this.findViewById(R.id.remove); - remove.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - // TODO Auto-generated method stub - if (mSamples.isEmpty()) - return; - - String name = (String)mResult.getSelectedItem(); - Gesture gesture = mSamples.get(mCurrentGestureIndex); - mRecognizer.removeGesture(name, gesture); - - mSamples = mRecognizer.getGestures(name); - - if (mSamples == null) { - // delete the entire entry - mCurrentGestureIndex = 0; - ArrayList<String> list = new ArrayList<String>(); - list.addAll(mRecognizer.getLabels()); - Collections.sort(list); - ArrayAdapter<String> adapter = new ArrayAdapter<String>( - GestureLibViewer.this, - android.R.layout.simple_spinner_item, - list); - adapter.setDropDownViewResource( - android.R.layout.simple_spinner_dropdown_item); - mResult.setAdapter(adapter); - } else { - if (mCurrentGestureIndex > mSamples.size()-1) { - mCurrentGestureIndex--; - } - gesture = mSamples.get(mCurrentGestureIndex); - mView.setCurrentGesture(gesture); - mView.clearDebugPath(); - mView.addDebugPath( - toPath(mRecognizer.getClassifier().getInstance(gesture.getID()))); - mView.invalidate(); - } } + }); - - Button next = (Button)this.findViewById(R.id.next); + + Button remove = (Button) findViewById(R.id.remove); + remove.setOnClickListener(new RemoveGestureListener()); + + Button next = (Button) findViewById(R.id.next); next.setOnClickListener(new OnClickListener() { public void onClick(View v) { - // TODO Auto-generated method stub - if (mCurrentGestureIndex >= mSamples.size()-1) + if (mCurrentGestureIndex >= mGestures.size() - 1) { return; - + } mCurrentGestureIndex++; - Gesture gesture = mSamples.get(mCurrentGestureIndex); - mView.setCurrentGesture(gesture); - mView.clearDebugPath(); - mView.addDebugPath( - toPath(mRecognizer.getClassifier().getInstance(gesture.getID()))); - mView.invalidate(); + Gesture gesture = mGestures.get(mCurrentGestureIndex); + mGesturePad.setCurrentGesture(gesture); + mGesturePad.invalidate(); } }); - Button previous = (Button)this.findViewById(R.id.previous); + Button previous = (Button) findViewById(R.id.previous); previous.setOnClickListener(new OnClickListener() { public void onClick(View v) { - // TODO Auto-generated method stub - if (mCurrentGestureIndex >= 1 && - mSamples.isEmpty() == false) { + if (mCurrentGestureIndex >= 1 && !mGestures.isEmpty()) { mCurrentGestureIndex--; - Gesture gesture = mSamples.get(mCurrentGestureIndex); - mView.setCurrentGesture(gesture); - mView.clearDebugPath(); - mView.addDebugPath( - toPath(mRecognizer.getClassifier().getInstance(gesture.getID()))); - mView.invalidate(); + Gesture gesture = mGestures.get(mCurrentGestureIndex); + mGesturePad.setCurrentGesture(gesture); + mGesturePad.invalidate(); } } }); } - - public static ArrayList<Path> toPath(Instance instance) { - ArrayList<Path> paths = new ArrayList(); - Path path = null; - float minx = 0, miny = 0; - float mX = 0, mY = 0; - for (int i=0; i<instance.vector.length; i+=2) { - float x = instance.vector[i]; - float y = instance.vector[i+1]; - if (x < minx) - minx = x; - if (y < miny) - miny = y; - if (path == null) { - path = new Path(); - path.moveTo(x, y); - mX = x; - mY = y; - } else { - float dx = Math.abs(x - mX); - float dy = Math.abs(y - mY); - if (dx >= 3 || dy >= 3) { - path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2); - mX = x; - mY = y; - } - } - } - Matrix matrix = new Matrix(); - matrix.setTranslate(-minx + 10, -miny + 10); - path.transform(matrix); - paths.add(path); - - path = new Path(); - path.moveTo(instance.vector[0]-5, instance.vector[1]-5); - path.lineTo(instance.vector[0]-5, instance.vector[1]+5); - path.lineTo(instance.vector[0]+5, instance.vector[1]+5); - path.lineTo(instance.vector[0]+5, instance.vector[1]-5); - path.close(); - path.transform(matrix); - paths.add(path); - - return paths; - } - + @Override public boolean onKeyUp(int keyCode, KeyEvent event) { - // TODO Auto-generated method stub - if (keyCode == KeyEvent.KEYCODE_BACK) { - mRecognizer.save(); - this.setResult(RESULT_OK); - finish(); - return true; - } - else - return false; + if (keyCode == KeyEvent.KEYCODE_BACK) { + mGesureLibrary.save(); + setResult(RESULT_OK); + finish(); + return true; + } else { + return false; + } } - + @Override protected void onPause() { - // TODO Auto-generated method stub super.onPause(); - mRecognizer.save(); + mGesureLibrary.save(); } @Override protected void onSaveInstanceState(Bundle outState) { - // TODO Auto-generated method stub super.onSaveInstanceState(outState); - mRecognizer.save(); + mGesureLibrary.save(); } } diff --git a/tests/sketch/src/com/android/gesture/recognizer/Classifier.java b/tests/sketch/src/com/android/gesture/recognizer/Classifier.java deleted file mode 100755 index 584e0a5..0000000 --- a/tests/sketch/src/com/android/gesture/recognizer/Classifier.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2008 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 com.android.gesture.recognizer; - -import java.util.ArrayList; -import java.util.HashMap; - -/** - * The abstract class of Classifier - */ -public abstract class Classifier { - - HashMap<Long, Instance> mInstances = new HashMap<Long, Instance>(); - - public void addInstance(Instance instance) { - mInstances.put(instance.id, instance); - } - - public Instance getInstance(long id) { - return mInstances.get(id); - } - - public void removeInstance(long id) { - mInstances.remove(id); - } - - public abstract ArrayList<Prediction> classify(Instance instance); -} diff --git a/tests/sketch/src/com/android/gesture/recognizer/Instance.java b/tests/sketch/src/com/android/gesture/recognizer/Instance.java deleted file mode 100755 index 2eaa1c2..0000000 --- a/tests/sketch/src/com/android/gesture/recognizer/Instance.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2008 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 com.android.gesture.recognizer; - -import android.graphics.PointF; - -import com.android.gesture.Gesture; - -/** - * An instance represents a sample if the label is available or a query if - * the label is null. - */ -public class Instance { - - private final static float[] targetOrientations = { - 0, 45, 90, 135, 180, -0, -45, -90, -135, -180 - }; - - // the feature vector - public final float[] vector; - // the label can be null - public final String label; - // the length of the vector - public final float length; - // the id of the instance - public final long id; - - Instance(long d, float[] v, String l) { - id = d; - vector = v; - label = l; - float sum = 0; - for (int i = 0; i < vector.length; i++) { - sum += vector[i] * vector[i]; - } - length = (float)Math.sqrt(sum); - } - - public static Instance createInstance(Gesture gesture, String label) { - float[] pts = RecognitionUtil.resample(gesture, 64); - PointF center = RecognitionUtil.computeCentroid(pts); - float inductiveOrientation = (float)Math.atan2(pts[1] - center.y, - pts[0] - center.x); - inductiveOrientation *= 180 / Math.PI; - - float minDeviation = Float.MAX_VALUE; - for (int i=0; i<targetOrientations.length; i++) { - float delta = targetOrientations[i] - inductiveOrientation; - if (Math.abs(delta) < Math.abs(minDeviation)) { - minDeviation = delta; - } - } - - android.graphics.Matrix m = new android.graphics.Matrix(); - m.setTranslate(-center.x, -center.y); - android.graphics.Matrix rotation = new android.graphics.Matrix(); - rotation.setRotate(minDeviation); - m.postConcat(rotation); - m.mapPoints(pts); - - return new Instance(gesture.getID(), pts, label); - } -} diff --git a/tests/sketch/src/com/android/gesture/recognizer/NearestNeighbor.java b/tests/sketch/src/com/android/gesture/recognizer/NearestNeighbor.java deleted file mode 100755 index cb8a9d3..0000000 --- a/tests/sketch/src/com/android/gesture/recognizer/NearestNeighbor.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2008 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 com.android.gesture.recognizer; - -import android.util.Log; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.TreeMap; - -public class NearestNeighbor extends Classifier { - - private static final String LOGTAG = "NearestNeighbor"; - private static final double variance = 0.25; // std = 0.5 - - public ArrayList<Prediction> classify(Instance instance) { - - ArrayList<Prediction> list = new ArrayList<Prediction>(); - Iterator<Instance> it = mInstances.values().iterator(); - Log.v(LOGTAG, mInstances.size() + " instances found"); - TreeMap<String, Double> label2score = new TreeMap<String, Double>(); - while (it.hasNext()) { - Instance sample = it.next(); - double dis = RecognitionUtil.cosineDistance(sample, instance); - double weight = Math.exp(-dis*dis/(2 * variance)); - Log.v(LOGTAG, sample.label + " = " + dis + " weight = " + weight); - Double score = label2score.get(sample.label); - if (score == null) { - score = weight; - } - else { - score += weight; - } - label2score.put(sample.label, score); - } - - double sum = 0; - Iterator it2 = label2score.keySet().iterator(); - while (it2.hasNext()) { - String name = (String)it2.next(); - double score = label2score.get(name); - sum += score; - list.add(new Prediction(name, score)); - } - - it2 = list.iterator(); - while (it2.hasNext()) { - Prediction name = (Prediction)it2.next(); - name.score /= sum; - } - - - Collections.sort(list, new Comparator<Prediction>() { - public int compare(Prediction object1, Prediction object2) { - // TODO Auto-generated method stub - double score1 = object1.score; - double score2 = object2.score; - if (score1 > score2) - return -1; - else if (score1 < score2) - return 1; - else - return 0; - } - }); - - it2 = list.iterator(); - while (it2.hasNext()) { - Prediction name = (Prediction)it2.next(); - Log.v(LOGTAG, "prediction [" + name.label + " = " + name.score + "]"); - } - - return list; - } -} diff --git a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java b/tests/sketch/src/com/android/gesture/recognizer/Prediction.java deleted file mode 100755 index c318754..0000000 --- a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2008 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 com.android.gesture.recognizer; - -/** - * - * A recognition result that includes the label and its score - */ -public class Prediction { - public final String label; - public double score; - - public Prediction(String l, double s) { - label = l; - score = s; - } - - @Override - public String toString() { - return label; - } -} diff --git a/tests/sketch/src/com/android/gesture/recognizer/RecognitionUtil.java b/tests/sketch/src/com/android/gesture/recognizer/RecognitionUtil.java deleted file mode 100755 index 9146b95..0000000 --- a/tests/sketch/src/com/android/gesture/recognizer/RecognitionUtil.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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 com.android.gesture.recognizer; - -import android.graphics.PointF; - -import com.android.gesture.Gesture; - -import java.util.Iterator; - -/** - * - * Utilities for recognition. - */ - -public class RecognitionUtil { - - /** - * Re-sample a list of points to a given number - * @param stk - * @param num - * @return - */ - public static float[] resample(Gesture gesture, int num) { - final float increment = gesture.getLength()/(num - 1); - float[] newstk = new float[num*2]; - float distanceSoFar = 0; - Iterator<PointF> it = gesture.getPoints().iterator(); - PointF lstPoint = it.next(); - int index = 0; - PointF currentPoint = null; - try - { - newstk[index] = lstPoint.x; - index++; - newstk[index] = lstPoint.y; - index++; - while (it.hasNext()) { - if (currentPoint == null) - currentPoint = it.next(); - float deltaX = currentPoint.x - lstPoint.x; - float deltaY = currentPoint.y - lstPoint.y; - float distance = (float)Math.sqrt(deltaX*deltaX+deltaY*deltaY); - if (distanceSoFar+distance >= increment) { - float ratio = (increment - distanceSoFar) / distance; - float nx = lstPoint.x + ratio * deltaX; - float ny = lstPoint.y + ratio * deltaY; - newstk[index] = nx; - index++; - newstk[index] = ny; - index++; - lstPoint = new PointF(nx, ny); - distanceSoFar = 0; - } - else { - lstPoint = currentPoint; - currentPoint = null; - distanceSoFar += distance; - } - } - } - catch(Exception ex) { - ex.printStackTrace(); - } - - for(int i = index; i < newstk.length -1; i+=2) { - newstk[i] = lstPoint.x; - newstk[i+1] = lstPoint.y; - } - return newstk; - } - - /** - * Calculate the centroid of a list of points - * @param points - * @return the centroid - */ - public static PointF computeCentroid(float[] points) { - float centerX = 0; - float centerY = 0; - for(int i=0; i<points.length; i++) - { - centerX += points[i]; - i++; - centerY += points[i]; - } - centerX = 2 * centerX/points.length; - centerY = 2 * centerY/points.length; - return new PointF(centerX, centerY); - } - - /** - * calculate the variance-covariance matrix, treat each point as a sample - * @param points - * @return - */ - public static double[][] computeCoVariance(float[] points) { - double[][] array = new double[2][2]; - array[0][0] = 0; - array[0][1] = 0; - array[1][0] = 0; - array[1][1] = 0; - for(int i=0; i<points.length; i++) - { - float x = points[i]; - i++; - float y = points[i]; - array[0][0] += x * x; - array[0][1] += x * y; - array[1][0] = array[0][1]; - array[1][1] += y * y; - } - array[0][0] /= (points.length/2); - array[0][1] /= (points.length/2); - array[1][0] /= (points.length/2); - array[1][1] /= (points.length/2); - - return array; - } - - - public static float computeTotalLength(float[] points) { - float sum = 0; - for (int i=0; i<points.length - 4; i+=2) { - float dx = points[i+2] - points[i]; - float dy = points[i+3] - points[i+1]; - sum += Math.sqrt(dx*dx + dy*dy); - } - return sum; - } - - public static double computeStraightness(float[] points) { - float totalLen = computeTotalLength(points); - float dx = points[2] - points[0]; - float dy = points[3] - points[1]; - return Math.sqrt(dx*dx + dy*dy) / totalLen; - } - - public static double computeStraightness(float[] points, float totalLen) { - float dx = points[2] - points[0]; - float dy = points[3] - points[1]; - return Math.sqrt(dx*dx + dy*dy) / totalLen; - } - - public static double averageEuclidDistance(float[] stk1, float[] stk2) { - double distance = 0; - for (int i = 0; i < stk1.length; i += 2) { - distance += PointF.length(stk1[i] - stk2[i], stk1[i+1] - stk2[i+1]); - } - return distance/stk1.length; - } - - public static double squaredEuclidDistance(float[] stk1, float[] stk2) { - double squaredDistance = 0; - for (int i = 0; i < stk1.length; i++) { - float difference = stk1[i] - stk2[i]; - squaredDistance += difference * difference; - } - return squaredDistance/stk1.length; - } - - /** - * Calculate the cosine distance between two instances - * @param in1 - * @param in2 - * @return the angle between 0 and Math.PI - */ - public static double cosineDistance(Instance in1, Instance in2) { - float sum = 0; - for (int i = 0; i < in1.vector.length; i++) { - sum += in1.vector[i] * in2.vector[i]; - } - return Math.acos(sum / (in1.length * in2.length)); - } - -} diff --git a/tests/sketch/tools/Converter.java b/tests/sketch/tools/Converter.java new file mode 100644 index 0000000..c0391d8 --- /dev/null +++ b/tests/sketch/tools/Converter.java @@ -0,0 +1,224 @@ +import java.io.File; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.Closeable; +import java.io.DataOutputStream; +import java.io.FileOutputStream; +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.io.BufferedInputStream; + +/** + * Converts text-based letter stores to binary-based stores. + */ +public class Converter { + private final File mFile; + private static final short VERSION_NUMBER = 1; + + Converter(File file) { + mFile = file; + } + + private void convert() { + boolean read = false; + + String[] classes = null; + int iCount = 0; + int hCount = 0; + int oCount = 0; + float[][] iWeights = null; + float[][] oWeights = null; + + BufferedReader reader = null; + + try { + reader = new BufferedReader(new FileReader(mFile)); + + long start = System.nanoTime(); + + String line = reader.readLine(); + int startIndex = 0; + int endIndex; + endIndex = line.indexOf(" ", startIndex); + iCount = Integer.parseInt(line.substring(startIndex, endIndex)); + + startIndex = endIndex + 1; + endIndex = line.indexOf(" ", startIndex); + hCount = Integer.parseInt(line.substring(startIndex, endIndex)); + + startIndex = endIndex + 1; + endIndex = line.length(); + oCount = Integer.parseInt(line.substring(startIndex, endIndex)); + + classes = new String[oCount]; + line = reader.readLine(); + startIndex = 0; + + for (int i = 0; i < oCount; i++) { + endIndex = line.indexOf(" ", startIndex); + classes[i] = line.substring(startIndex, endIndex); + startIndex = endIndex + 1; + } + + iWeights = new float[hCount][]; + for (int i = 0; i < hCount; i++) { + iWeights[i] = new float[iCount + 1]; + line = reader.readLine(); + startIndex = 0; + for (int j = 0; j <= iCount; j++) { + endIndex = line.indexOf(" ", startIndex); + iWeights[i][j] = Float.parseFloat(line.substring(startIndex, endIndex)); + startIndex = endIndex + 1; + } + } + + oWeights = new float[oCount][]; + for (int i = 0; i < oCount; i++) { + oWeights[i] = new float[hCount + 1]; + line = reader.readLine(); + startIndex = 0; + for (int j = 0; j <= hCount; j++) { + endIndex = line.indexOf(" ", startIndex); + oWeights[i][j] = Float.parseFloat(line.substring(startIndex, endIndex)); + startIndex = endIndex + 1; + } + } + + long end = System.nanoTime(); + System.out.println("time to read text file = " + + ((end - start) / 1000.0f / 1000.0f) + " ms"); + + read = true; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + close(reader); + } + + if (read) { + boolean wrote = false; + DataOutputStream out = null; + + try { + out = new DataOutputStream(new FileOutputStream(mFile)); + + out.writeShort(VERSION_NUMBER); + out.writeInt(iCount); + out.writeInt(hCount); + out.writeInt(oCount); + + for (String aClass : classes) { + out.writeUTF(aClass); + } + + for (float[] weights : iWeights) { + for (float weight : weights) { + out.writeFloat(weight); + } + } + + for (float[] weights : oWeights) { + for (float weight : weights) { + out.writeFloat(weight); + } + } + + out.flush(); + + wrote = true; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + close(out); + } + + if (wrote) { + DataInputStream in = null; + + try { + in = new DataInputStream(new BufferedInputStream(new FileInputStream(mFile))); + + long start = System.nanoTime(); + + iCount = in.readInt(); + hCount = in.readInt(); + oCount = in.readInt(); + + classes = new String[oCount]; + for (int i = 0; i < classes.length; i++) { + classes[i] = in.readUTF(); + } + + iWeights = new float[hCount][]; + for (int i = 0; i < iWeights.length; i++) { + iWeights[i] = new float[iCount]; + for (int j = 0; j < iCount; j++) { + iWeights[i][j] = in.readFloat(); + } + } + + oWeights = new float[oCount][]; + for (int i = 0; i < oWeights.length; i++) { + oWeights[i] = new float[hCount]; + for (int j = 0; j < hCount; j++) { + oWeights[i][j] = in.readFloat(); + } + } + + long end = System.nanoTime(); + System.out.println("time to read binary file = " + + ((end - start) / 1000.0f / 1000.0f) + " ms"); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + close(in); + } + } + } + } + + private static void close(Closeable reader) { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) { + String fileName = args[0]; + if (fileName != null) { + File file = new File(fileName); + if (!file.exists()) { + printHelp(fileName); + } else { + new Converter(file).convert(); + } + } else { + printHelp(null); + } + } + + private static void printHelp(String name) { + if (name == null) { + System.out.println("You must specify the name of the file to convert:"); + } else { + System.out.println("The specified file does not exist: " + name); + } + System.out.println("java Converter [filename]"); + System.out.println(""); + System.out.println("\t[filename]\tPath to the file to convert. The file is replaced by " + + "the conversion result."); + } +}
\ No newline at end of file |