summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--carousel/test/res/values-in/strings.xml2
-rw-r--r--chips/AndroidManifest.xml16
-rw-r--r--chips/res/values-ko/strings.xml2
-rw-r--r--chips/res/values-pt-rPT/strings.xml2
-rw-r--r--chips/src/com/android/ex/chips/RecipientEditTextView.java108
-rw-r--r--common/java/com/android/common/OperationScheduler.java53
-rw-r--r--common/tests/src/com/android/common/OperationSchedulerTest.java40
-rw-r--r--photoviewer/.gitignore8
-rw-r--r--variablespeed/jni/Android.mk1
-rw-r--r--variablespeed/jni/variablespeed.cc4
10 files changed, 167 insertions, 69 deletions
diff --git a/carousel/test/res/values-in/strings.xml b/carousel/test/res/values-in/strings.xml
index 40000e8..06c8812 100644
--- a/carousel/test/res/values-in/strings.xml
+++ b/carousel/test/res/values-in/strings.xml
@@ -21,7 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="music_demo_activity_label" msgid="4382090808250495841">"KaruselMusik"</string>
<string name="carousel_test_activity_label" msgid="6014624482213318747">"UjiKarusel"</string>
- <string name="carousel_test_activity_description" msgid="1632693812604375483">"Aplikasi untuk menampilkan penggunaan Karusel"</string>
+ <string name="carousel_test_activity_description" msgid="1632693812604375483">"Aplikasi untuk menampilkan penggunaan Korsel"</string>
<string name="task_switcher_activity_label" msgid="714620143340933546">"PengubahTugas"</string>
<string name="recent_tasks_title" msgid="1030287226205477117">"Aplikasi Terbaru"</string>
<string name="no_recent_tasks" msgid="6884096266670555780">"Tidak ada tugas terbaru"</string>
diff --git a/chips/AndroidManifest.xml b/chips/AndroidManifest.xml
index e159fd2..fd7775d 100644
--- a/chips/AndroidManifest.xml
+++ b/chips/AndroidManifest.xml
@@ -1,5 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.ex.chips"
android:versionCode="1">
-</manifest> \ No newline at end of file
+</manifest>
diff --git a/chips/res/values-ko/strings.xml b/chips/res/values-ko/strings.xml
index 7423ce5..f7884bd 100644
--- a/chips/res/values-ko/strings.xml
+++ b/chips/res/values-ko/strings.xml
@@ -19,5 +19,5 @@
<string name="more_string" msgid="8495478259330621990">"<xliff:g id="COUNT">%1$s</xliff:g>명 이상"</string>
<string name="copy_email" msgid="7869435992461603532">"이메일 주소 복사"</string>
<string name="copy_number" msgid="530057841276106843">"전화번호 복사"</string>
- <string name="done" msgid="2356320650733788862">"Enter 키"</string>
+ <string name="done" msgid="2356320650733788862">"입력"</string>
</resources>
diff --git a/chips/res/values-pt-rPT/strings.xml b/chips/res/values-pt-rPT/strings.xml
index bfbe1ca..fc991b1 100644
--- a/chips/res/values-pt-rPT/strings.xml
+++ b/chips/res/values-pt-rPT/strings.xml
@@ -19,5 +19,5 @@
<string name="more_string" msgid="8495478259330621990">"+<xliff:g id="COUNT">%1$s</xliff:g>"</string>
<string name="copy_email" msgid="7869435992461603532">"Copiar endereço de email"</string>
<string name="copy_number" msgid="530057841276106843">"Copiar número de telefone"</string>
- <string name="done" msgid="2356320650733788862">"Regressar"</string>
+ <string name="done" msgid="2356320650733788862">"Voltar"</string>
</resources>
diff --git a/chips/src/com/android/ex/chips/RecipientEditTextView.java b/chips/src/com/android/ex/chips/RecipientEditTextView.java
index 41bab18..8b6367f 100644
--- a/chips/src/com/android/ex/chips/RecipientEditTextView.java
+++ b/chips/src/com/android/ex/chips/RecipientEditTextView.java
@@ -57,6 +57,7 @@ import android.text.InputType;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
@@ -409,6 +410,44 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
}
+ private int getExcessTopPadding() {
+ if (sExcessTopPadding == -1) {
+ sExcessTopPadding = (int) (mChipHeight + mLineSpacingExtra);
+ }
+ return sExcessTopPadding;
+ }
+
+ public <T extends ListAdapter & Filterable> void setAdapter(T adapter) {
+ super.setAdapter(adapter);
+ ((BaseRecipientAdapter) adapter)
+ .registerUpdateObserver(new BaseRecipientAdapter.EntriesUpdatedObserver() {
+ @Override
+ public void onChanged(List<RecipientEntry> entries) {
+ // Scroll the chips field to the top of the screen so
+ // that the user can see as many results as possible.
+ if (entries != null && entries.size() > 0) {
+ scrollBottomIntoView();
+ }
+ }
+ });
+ }
+
+ private void scrollBottomIntoView() {
+ if (mScrollView != null && mShouldShrink) {
+ int[] location = new int[2];
+ getLocationOnScreen(location);
+ int height = getHeight();
+ int currentPos = location[1] + height;
+ // Desired position shows at least 1 line of chips below the action
+ // bar. We add excess padding to make sure this is always below other
+ // content.
+ int desiredPos = (int) mChipHeight + mActionBarHeight + getExcessTopPadding();
+ if (currentPos > desiredPos) {
+ mScrollView.scrollBy(0, currentPos - desiredPos);
+ }
+ }
+ }
+
@Override
public void performValidation() {
// Do nothing. Chips handles its own validation.
@@ -921,7 +960,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
String token = editable.toString().substring(tokenStart, tokenEnd);
final String trimmedToken = token.trim();
int commitCharIndex = trimmedToken.lastIndexOf(COMMIT_CHAR_COMMA);
- if (commitCharIndex == trimmedToken.length() - 1) {
+ if (commitCharIndex != -1 && commitCharIndex == trimmedToken.length() - 1) {
token = trimmedToken.substring(0, trimmedToken.length() - 1);
}
RecipientEntry entry = createTokenizedEntry(token);
@@ -1600,6 +1639,9 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
*/
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (position < 0) {
+ return;
+ }
submitItemAtPosition(position);
}
@@ -2249,45 +2291,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
}
- @Override
- public <T extends ListAdapter & Filterable> void setAdapter(T adapter) {
- super.setAdapter(adapter);
- ((BaseRecipientAdapter) adapter)
- .registerUpdateObserver(new BaseRecipientAdapter.EntriesUpdatedObserver() {
- @Override
- public void onChanged(List<RecipientEntry> entries) {
- if (entries != null && entries.size() > 0) {
- scrollBottomIntoView();
- }
- }
- });
- }
-
- private void scrollBottomIntoView() {
- if (mScrollView != null && mShouldShrink) {
- int[] location = new int[2];
- getLocationOnScreen(location);
- int height = getHeight();
- int currentPos = location[1] + height;
- // Desired position shows at least 1 line of chips below the action
- // bar.
- // We add excess padding to make sure this is always below other
- // content.
- int desiredPos = (int) mChipHeight + mActionBarHeight + getExcessTopPadding();
- if (currentPos > desiredPos) {
- mScrollView.scrollBy(0, currentPos - desiredPos);
- }
- }
- }
-
- private int getExcessTopPadding() {
- if (sExcessTopPadding == -1) {
- sExcessTopPadding = (int) (mChipHeight + mLineSpacingExtra);
- }
- return sExcessTopPadding;
- }
-
- public boolean lastCharacterIsCommitCharacter(CharSequence s) {
+ public boolean lastCharacterIsCommitCharacter(CharSequence s) {
char last;
int end = getSelectionEnd() == 0 ? 0 : getSelectionEnd() - 1;
int len = length() - 1;
@@ -2366,6 +2370,9 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
prevTokenStart = tokenStart;
tokenStart = mTokenizer.findTokenStart(text, tokenStart);
findChip = findChip(tokenStart);
+ if (tokenStart == originalTokenStart && findChip == null) {
+ break;
+ }
}
if (tokenStart != originalTokenStart) {
if (findChip != null) {
@@ -2542,11 +2549,10 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
final Runnable runnable = new Runnable() {
@Override
public void run() {
- Editable oldText = getText();
- int start, end;
+ final Editable text = new SpannableStringBuilder(getText());
int i = 0;
- for (DrawableRecipientChip chip : recipients) {
- DrawableRecipientChip replacement = replacements.get(i);
+ for (final DrawableRecipientChip chip : recipients) {
+ final DrawableRecipientChip replacement = replacements.get(i);
if (replacement != null) {
final RecipientEntry oldEntry = chip.getEntry();
final RecipientEntry newEntry = replacement.getEntry();
@@ -2556,25 +2562,24 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
if (isBetter) {
// Find the location of the chip in the text currently shown.
- start = oldText.getSpanStart(chip);
+ final int start = text.getSpanStart(chip);
if (start != -1) {
// Replacing the entirety of what the chip represented,
// including the extra space dividing it from other chips.
- end = oldText.getSpanEnd(chip) + 1;
- oldText.removeSpan(chip);
+ final int end = text.getSpanEnd(chip) + 1;
+ text.removeSpan(chip);
// Make sure we always have just 1 space at the end to
// separate this chip from the next chip.
- SpannableString displayText =
+ final SpannableString displayText =
new SpannableString(createAddressText(
- replacement.getEntry()).trim()
- + " ");
+ replacement.getEntry()).trim() + " ");
displayText.setSpan(replacement, 0,
displayText.length() - 1,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// Replace the old text we found with with the new display
// text, which now may also contain the display name of the
// recipient.
- oldText.replace(start, end, displayText);
+ text.replace(start, end, displayText);
replacement.setOriginalText(displayText.toString());
replacements.set(i, null);
@@ -2584,6 +2589,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
i++;
}
+ setText(text);
}
};
diff --git a/common/java/com/android/common/OperationScheduler.java b/common/java/com/android/common/OperationScheduler.java
index b8fc7bc..261b15d 100644
--- a/common/java/com/android/common/OperationScheduler.java
+++ b/common/java/com/android/common/OperationScheduler.java
@@ -42,6 +42,9 @@ public class OperationScheduler {
/** Wait this long times the number of consecutive errors so far before retrying. */
public long backoffIncrementalMillis = 5000;
+ /** Wait this long times 2^(number of consecutive errors so far) before retrying. */
+ public int backoffExponentialMillis = 0;
+
/** Maximum duration of moratorium to honor. Mostly an issue for clock rollbacks. */
public long maxMoratoriumMillis = 24 * 3600 * 1000;
@@ -53,11 +56,20 @@ public class OperationScheduler {
@Override
public String toString() {
- return String.format(
+ if (backoffExponentialMillis > 0) {
+ return String.format(
+ "OperationScheduler.Options[backoff=%.1f+%.1f+%.1f max=%.1f min=%.1f period=%.1f]",
+ backoffFixedMillis / 1000.0, backoffIncrementalMillis / 1000.0,
+ backoffExponentialMillis / 1000.0,
+ maxMoratoriumMillis / 1000.0, minTriggerMillis / 1000.0,
+ periodicIntervalMillis / 1000.0);
+ } else {
+ return String.format(
"OperationScheduler.Options[backoff=%.1f+%.1f max=%.1f min=%.1f period=%.1f]",
backoffFixedMillis / 1000.0, backoffIncrementalMillis / 1000.0,
maxMoratoriumMillis / 1000.0, minTriggerMillis / 1000.0,
periodicIntervalMillis / 1000.0);
+ }
}
}
@@ -76,7 +88,7 @@ public class OperationScheduler {
* Parse scheduler options supplied in this string form:
*
* <pre>
- * backoff=(fixed)+(incremental) max=(maxmoratorium) min=(mintrigger) [period=](interval)
+ * backoff=(fixed)+(incremental)[+(exponential)] max=(maxmoratorium) min=(mintrigger) [period=](interval)
* </pre>
*
* All values are times in (possibly fractional) <em>seconds</em> (not milliseconds).
@@ -97,14 +109,18 @@ public class OperationScheduler {
for (String param : spec.split(" +")) {
if (param.length() == 0) continue;
if (param.startsWith("backoff=")) {
- int plus = param.indexOf('+', 8);
- if (plus < 0) {
- options.backoffFixedMillis = parseSeconds(param.substring(8));
- } else {
- if (plus > 8) {
- options.backoffFixedMillis = parseSeconds(param.substring(8, plus));
- }
- options.backoffIncrementalMillis = parseSeconds(param.substring(plus + 1));
+ String[] pieces = param.substring(8).split("\\+");
+ if (pieces.length > 3) {
+ throw new IllegalArgumentException("bad value for backoff: [" + spec + "]");
+ }
+ if (pieces.length > 0 && pieces[0].length() > 0) {
+ options.backoffFixedMillis = parseSeconds(pieces[0]);
+ }
+ if (pieces.length > 1 && pieces[1].length() > 0) {
+ options.backoffIncrementalMillis = parseSeconds(pieces[1]);
+ }
+ if (pieces.length > 2 && pieces[2].length() > 0) {
+ options.backoffExponentialMillis = (int)parseSeconds(pieces[2]);
}
} else if (param.startsWith("max=")) {
options.maxMoratoriumMillis = parseSeconds(param.substring(4));
@@ -160,8 +176,21 @@ public class OperationScheduler {
time = Math.max(time, moratoriumTimeMillis);
time = Math.max(time, lastSuccessTimeMillis + options.minTriggerMillis);
if (errorCount > 0) {
- time = Math.max(time, lastErrorTimeMillis + options.backoffFixedMillis +
- options.backoffIncrementalMillis * errorCount);
+ int shift = errorCount-1;
+ // backoffExponentialMillis is an int, so we can safely
+ // double it 30 times without overflowing a long.
+ if (shift > 30) shift = 30;
+ long backoff = options.backoffFixedMillis +
+ (options.backoffIncrementalMillis * errorCount) +
+ (((long)options.backoffExponentialMillis) << shift);
+
+ // Treat backoff like a moratorium: don't let the backoff
+ // time grow too large.
+ if (moratoriumTimeMillis > 0 && backoff > moratoriumTimeMillis) {
+ backoff = moratoriumTimeMillis;
+ }
+
+ time = Math.max(time, lastErrorTimeMillis + backoff);
}
return time;
}
diff --git a/common/tests/src/com/android/common/OperationSchedulerTest.java b/common/tests/src/com/android/common/OperationSchedulerTest.java
index 955508f..87e2cd8 100644
--- a/common/tests/src/com/android/common/OperationSchedulerTest.java
+++ b/common/tests/src/com/android/common/OperationSchedulerTest.java
@@ -119,6 +119,42 @@ public class OperationSchedulerTest extends AndroidTestCase {
assertEquals(beforeSuccess + 1000000, scheduler.getNextTimeMillis(options));
}
+ @MediumTest
+ public void testExponentialBackoff() throws Exception {
+ TimeTravelScheduler scheduler = new TimeTravelScheduler();
+ OperationScheduler.Options options = new OperationScheduler.Options();
+ options.backoffFixedMillis = 100;
+ options.backoffIncrementalMillis = 1000;
+ options.backoffExponentialMillis = 10000;
+ scheduler.setTriggerTimeMillis(0);
+ scheduler.setEnabledState(true);
+
+ // Backoff interval after an error
+ long beforeError = (scheduler.timeMillis += 10);
+ scheduler.onTransientError();
+ assertEquals(0, scheduler.getLastSuccessTimeMillis());
+ assertEquals(beforeError, scheduler.getLastAttemptTimeMillis());
+ assertEquals(beforeError + 11100, scheduler.getNextTimeMillis(options));
+
+ // Second error
+ beforeError = (scheduler.timeMillis += 10);
+ scheduler.onTransientError();
+ assertEquals(beforeError, scheduler.getLastAttemptTimeMillis());
+ assertEquals(beforeError + 22100, scheduler.getNextTimeMillis(options));
+
+ // Third error
+ beforeError = (scheduler.timeMillis += 10);
+ scheduler.onTransientError();
+ assertEquals(beforeError, scheduler.getLastAttemptTimeMillis());
+ assertEquals(beforeError + 43100, scheduler.getNextTimeMillis(options));
+
+ // Fourth error
+ beforeError = (scheduler.timeMillis += 10);
+ scheduler.onTransientError();
+ assertEquals(beforeError, scheduler.getLastAttemptTimeMillis());
+ assertEquals(beforeError + 84100, scheduler.getNextTimeMillis(options));
+ }
+
@SmallTest
public void testParseOptions() throws Exception {
OperationScheduler.Options options = new OperationScheduler.Options();
@@ -138,6 +174,10 @@ public class OperationSchedulerTest extends AndroidTestCase {
assertEquals(
"OperationScheduler.Options[backoff=10.0+2.5 max=12345.6 min=7.0 period=3800.0]",
OperationScheduler.parseOptions("", options).toString());
+
+ assertEquals(
+ "OperationScheduler.Options[backoff=5.0+2.5+10.0 max=12345.6 min=7.0 period=3600.0]",
+ OperationScheduler.parseOptions("backoff=5.0++10.0 3600", options).toString());
}
@SmallTest
diff --git a/photoviewer/.gitignore b/photoviewer/.gitignore
new file mode 100644
index 0000000..ff7ef7d
--- /dev/null
+++ b/photoviewer/.gitignore
@@ -0,0 +1,8 @@
+*~
+*.bak
+*.class
+bin/
+gen/
+*.properties
+.classpath
+.project
diff --git a/variablespeed/jni/Android.mk b/variablespeed/jni/Android.mk
index 66ec1c5..08de535 100644
--- a/variablespeed/jni/Android.mk
+++ b/variablespeed/jni/Android.mk
@@ -44,6 +44,7 @@ LOCAL_SHARED_LIBRARIES := \
libstlport \
libutils \
libcutils \
+ liblog \
LOCAL_LDLIBS := \
-lOpenSLES \
diff --git a/variablespeed/jni/variablespeed.cc b/variablespeed/jni/variablespeed.cc
index ea134ec..73ac609 100644
--- a/variablespeed/jni/variablespeed.cc
+++ b/variablespeed/jni/variablespeed.cc
@@ -582,7 +582,7 @@ static void CreateAndRealizeAudioPlayer(SLuint32 slSampleRate,
const size_t playerInterfaceCount = 2;
const SLInterfaceID iids[playerInterfaceCount] = {
SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION };
- const SLboolean reqs[playerInterfaceCount] = { SL_BOOLEAN_TRUE };
+ const SLboolean reqs[playerInterfaceCount] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
OpenSL(engineInterface, CreateAudioPlayer, &audioPlayer, &playingSrc,
&audioSnk, playerInterfaceCount, iids, reqs);
setAudioStreamType(audioPlayer, audioStreamType);
@@ -619,7 +619,7 @@ bool AudioEngine::PlayFromThisSource(const SLDataSource& audioSrc) {
SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_PREFETCHSTATUS, SL_IID_SEEK,
SL_IID_METADATAEXTRACTION, SL_IID_ANDROIDCONFIGURATION };
const SLboolean decodePlayerRequired[decoderInterfaceCount] = {
- SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
+ SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
SLDataSource sourceCopy(audioSrc);
OpenSL(engineInterface, CreateAudioPlayer, &decoder, &sourceCopy, &decDest,
decoderInterfaceCount, decodePlayerInterfaces, decodePlayerRequired);