Merge "Fix 2797185: Integrate 3D RecentApps View into system."
diff --git a/api/current.xml b/api/current.xml
index cbbf3d1..ebb8b3e 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -19870,6 +19870,17 @@
visibility="public"
>
</method>
+<method name="isRunning"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="removeAllListeners"
return="void"
abstract="false"
@@ -19966,6 +19977,40 @@
</parameter>
</method>
</interface>
+<class name="AnimatableInflater"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="AnimatableInflater"
+ type="android.animation.AnimatableInflater"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="loadAnimatable"
+ return="android.animation.Animatable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="id" type="int">
+</parameter>
+<exception name="Resources.NotFoundException" type="android.content.res.Resources.NotFoundException">
+</exception>
+</method>
+</class>
<class name="AnimatableListenerAdapter"
extends="java.lang.Object"
abstract="true"
@@ -20052,10 +20097,6 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="attrs" type="android.util.AttributeSet">
-</parameter>
</constructor>
<constructor name="Animator"
type="android.animation.Animator"
@@ -20231,6 +20272,19 @@
<parameter name="playTime" type="long">
</parameter>
</method>
+<method name="setDuration"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="duration" type="long">
+</parameter>
+</method>
<method name="setEvaluator"
return="void"
abstract="false"
@@ -20653,10 +20707,6 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="attrs" type="android.util.AttributeSet">
-</parameter>
</constructor>
<constructor name="PropertyAnimator"
type="android.animation.PropertyAnimator"
@@ -20929,6 +20979,17 @@
visibility="public"
>
</method>
+<method name="isRunning"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="play"
return="android.animation.Sequencer.Builder"
abstract="false"
@@ -51169,6 +51230,17 @@
<parameter name="key" type="java.lang.String">
</parameter>
</method>
+<method name="startCommit"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
</interface>
<interface name="SharedPreferences.OnSharedPreferenceChangeListener"
abstract="true"
@@ -205789,23 +205861,6 @@
<exception name="Resources.NotFoundException" type="android.content.res.Resources.NotFoundException">
</exception>
</method>
-<method name="loadAnimator"
- return="android.animation.Animatable"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="id" type="int">
-</parameter>
-<exception name="Resources.NotFoundException" type="android.content.res.Resources.NotFoundException">
-</exception>
-</method>
<method name="loadInterpolator"
return="android.view.animation.Interpolator"
abstract="false"
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 0f343ff..4265cc5 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -142,6 +142,11 @@
String value = nextArgRequired();
intent.putExtra(key, Integer.valueOf(value));
hasIntentInfo = true;
+ } else if (opt.equals("--el")) {
+ String key = nextArgRequired();
+ String value = nextArgRequired();
+ intent.putExtra(key, Long.valueOf(value));
+ hasIntentInfo = true;
} else if (opt.equals("--ez")) {
String key = nextArgRequired();
String value = nextArgRequired();
@@ -627,6 +632,7 @@
" [--esn <EXTRA_KEY> ...]\n" +
" [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
" [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
+ " [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
" [-n <COMPONENT>] [-f <FLAGS>]\n" +
" [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
" [--debug-log-resolution]\n" +
diff --git a/cmds/screenshot/screenshot.c b/cmds/screenshot/screenshot.c
index 46e6507..048636c 100644
--- a/cmds/screenshot/screenshot.c
+++ b/cmds/screenshot/screenshot.c
@@ -88,13 +88,61 @@
png_destroy_write_struct(&png, NULL);
}
+void fork_sound(const char* path) {
+ pid_t pid = fork();
+ if (pid == 0) {
+ execl("/system/bin/stagefright", "stagefright", "-o", "-a", path, NULL);
+ }
+}
+
+void usage() {
+ fprintf(stderr,
+ "usage: screenshot [-s soundfile] filename.png\n"
+ " -s: play a sound effect to signal success\n"
+ " -i: autoincrement to avoid overwriting filename.png\n"
+ );
+}
+
int main(int argc, char**argv) {
FILE *png = NULL;
FILE *fb_in = NULL;
- if (argc < 2) {
- fprintf(stderr, "usage: screenshot filename.png\n");
- exit(1);
+ char outfile[PATH_MAX] = "";
+
+ char * soundfile = NULL;
+ int do_increment = 0;
+
+ int c;
+ while ((c = getopt(argc, argv, "s:i")) != -1) {
+ switch (c) {
+ case 's': soundfile = optarg; break;
+ case 'i': do_increment = 1; break;
+ case '?':
+ case 'h':
+ usage(); exit(1);
+ }
}
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ usage(); exit(1);
+ }
+
+ strlcpy(outfile, argv[0], PATH_MAX);
+ if (do_increment) {
+ struct stat st;
+ char base[PATH_MAX] = "";
+ int i = 0;
+ while (stat(outfile, &st) == 0) {
+ if (!base[0]) {
+ char *p = strrchr(outfile, '.');
+ if (p) *p = '\0';
+ strcpy(base, outfile);
+ }
+ snprintf(outfile, PATH_MAX, "%s-%d.png", base, ++i);
+ }
+ }
+
fb_in = fopen("/dev/graphics/fb0", "r");
if (!fb_in) {
fprintf(stderr, "error: could not read framebuffer\n");
@@ -106,13 +154,18 @@
setgroups(sizeof(groups)/sizeof(groups[0]), groups);
setuid(AID_SHELL);
- png = fopen(argv[1], "w");
+ png = fopen(outfile, "w");
if (!png) {
- fprintf(stderr, "error: writing file %s: %s\n", argv[1], strerror(errno));
+ fprintf(stderr, "error: writing file %s: %s\n",
+ outfile, strerror(errno));
exit(1);
}
take_screenshot(fb_in, png);
+ if (soundfile) {
+ fork_sound(soundfile);
+ }
+
exit(0);
}
diff --git a/core/java/android/animation/Animatable.java b/core/java/android/animation/Animatable.java
index a49ca8f..d6cf7c0 100644
--- a/core/java/android/animation/Animatable.java
+++ b/core/java/android/animation/Animatable.java
@@ -56,6 +56,13 @@
public void end() {
}
+
+ /**
+ * Returns whether this Animatable is currently running (having been started and not yet ended).
+ * @return Whether the Animatable is running.
+ */
+ public abstract boolean isRunning();
+
/**
* Adds a listener to the set of listeners that are sent events through the life of an
* animation, such as start, repeat, and end.
diff --git a/core/java/android/animation/AnimatableInflater.java b/core/java/android/animation/AnimatableInflater.java
new file mode 100644
index 0000000..88fa77e
--- /dev/null
+++ b/core/java/android/animation/AnimatableInflater.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.content.res.Resources.NotFoundException;
+import android.util.AttributeSet;
+import android.util.Xml;
+import android.view.animation.AnimationUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * This class is used to instantiate menu XML files into Animatable objects.
+ * <p>
+ * For performance reasons, menu inflation relies heavily on pre-processing of
+ * XML files that is done at build time. Therefore, it is not currently possible
+ * to use MenuInflater with an XmlPullParser over a plain XML file at runtime;
+ * it only works with an XmlPullParser returned from a compiled resource (R.
+ * <em>something</em> file.)
+ */
+public class AnimatableInflater {
+
+ /**
+ * These flags are used when parsing Sequencer objects
+ */
+ private static final int TOGETHER = 0;
+ private static final int SEQUENTIALLY = 1;
+
+ /**
+ * Enum values used in XML attributes to indicate the value for mValueType
+ */
+ private static final int VALUE_TYPE_FLOAT = 0;
+ private static final int VALUE_TYPE_INT = 1;
+ private static final int VALUE_TYPE_DOUBLE = 2;
+ private static final int VALUE_TYPE_COLOR = 3;
+ private static final int VALUE_TYPE_CUSTOM = 4;
+
+ /**
+ * Loads an {@link Animatable} object from a resource
+ *
+ * @param context Application context used to access resources
+ * @param id The resource id of the animation to load
+ * @return The animatable object reference by the specified id
+ * @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
+ */
+ public static Animatable loadAnimatable(Context context, int id)
+ throws NotFoundException {
+
+ XmlResourceParser parser = null;
+ try {
+ parser = context.getResources().getAnimation(id);
+ return createAnimatableFromXml(context, parser);
+ } catch (XmlPullParserException ex) {
+ Resources.NotFoundException rnf =
+ new Resources.NotFoundException("Can't load animation resource ID #0x" +
+ Integer.toHexString(id));
+ rnf.initCause(ex);
+ throw rnf;
+ } catch (IOException ex) {
+ Resources.NotFoundException rnf =
+ new Resources.NotFoundException("Can't load animation resource ID #0x" +
+ Integer.toHexString(id));
+ rnf.initCause(ex);
+ throw rnf;
+ } finally {
+ if (parser != null) parser.close();
+ }
+ }
+
+ private static Animatable createAnimatableFromXml(Context c, XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+
+ return createAnimatableFromXml(c, parser, Xml.asAttributeSet(parser), null, 0);
+ }
+
+ private static Animatable createAnimatableFromXml(Context c, XmlPullParser parser,
+ AttributeSet attrs, Sequencer parent, int sequenceOrdering)
+ throws XmlPullParserException, IOException {
+
+ Animatable anim = null;
+ ArrayList<Animatable> childAnims = null;
+
+ // Make sure we are on a start tag.
+ int type;
+ int depth = parser.getDepth();
+
+ while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
+ && type != XmlPullParser.END_DOCUMENT) {
+
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ String name = parser.getName();
+
+ if (name.equals("property")) {
+ anim = loadPropertyAnimator(c, attrs);
+ } else if (name.equals("animator")) {
+ anim = loadAnimator(c, attrs, null);
+ } else if (name.equals("sequencer")) {
+ anim = new Sequencer();
+ TypedArray a = c.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.Sequencer);
+ int ordering = a.getInt(com.android.internal.R.styleable.Sequencer_ordering,
+ TOGETHER);
+ createAnimatableFromXml(c, parser, attrs, (Sequencer) anim, ordering);
+ a.recycle();
+ } else {
+ throw new RuntimeException("Unknown animator name: " + parser.getName());
+ }
+
+ if (parent != null) {
+ if (childAnims == null) {
+ childAnims = new ArrayList<Animatable>();
+ }
+ childAnims.add(anim);
+ }
+ }
+ if (parent != null && childAnims != null) {
+ Animatable[] animsArray = new Animatable[childAnims.size()];
+ int index = 0;
+ for (Animatable a : childAnims) {
+ animsArray[index++] = a;
+ }
+ if (sequenceOrdering == TOGETHER) {
+ parent.playTogether(animsArray);
+ } else {
+ parent.playSequentially(animsArray);
+ }
+ }
+
+ return anim;
+
+ }
+
+ private static PropertyAnimator loadPropertyAnimator(Context context, AttributeSet attrs)
+ throws NotFoundException {
+
+ PropertyAnimator anim = new PropertyAnimator();
+
+ loadAnimator(context, attrs, anim);
+
+ TypedArray a =
+ context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.PropertyAnimator);
+
+ String propertyName = a.getString(com.android.internal.R.styleable.PropertyAnimator_propertyName);
+
+ anim.setPropertyName(propertyName);
+
+ a.recycle();
+
+ return anim;
+ }
+
+ /**
+ * Creates a new animation whose parameters come from the specified context and
+ * attributes set.
+ *
+ * @param context the application environment
+ * @param attrs the set of attributes holding the animation parameters
+ */
+ private static Animator loadAnimator(Context context, AttributeSet attrs, Animator anim)
+ throws NotFoundException {
+
+ TypedArray a =
+ context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Animator);
+
+ long duration = a.getInt(com.android.internal.R.styleable.Animator_duration, 0);
+
+ long startDelay = a.getInt(com.android.internal.R.styleable.Animator_startOffset, 0);
+
+ int valueType = a.getInt(com.android.internal.R.styleable.Animator_valueType,
+ VALUE_TYPE_FLOAT);
+
+ Object valueFrom = null;
+ Object valueTo = null;
+ TypeEvaluator evaluator = null;
+
+ switch (valueType) {
+ case VALUE_TYPE_FLOAT:
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueFrom)) {
+ valueFrom = a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f);
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueTo)) {
+ valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
+ }
+ break;
+ case VALUE_TYPE_COLOR:
+ evaluator = new RGBEvaluator();
+ // fall through to pick up values
+ case VALUE_TYPE_INT:
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueFrom)) {
+ valueFrom = a.getInteger(com.android.internal.R.styleable.Animator_valueFrom, 0);
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueTo)) {
+ valueTo = a.getInteger(com.android.internal.R.styleable.Animator_valueTo, 0);
+ }
+ break;
+ case VALUE_TYPE_DOUBLE:
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueFrom)) {
+ valueFrom = (Double)((Float)(a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f))).doubleValue();
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueTo)) {
+ valueTo = (Double)((Float)a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f)).doubleValue();
+ }
+ break;
+ case VALUE_TYPE_CUSTOM:
+ // TODO: How to get an 'Object' value?
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueFrom)) {
+ valueFrom = a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f);
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueTo)) {
+ valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
+ }
+ break;
+ }
+
+ if (anim == null) {
+ anim = new Animator(duration, valueFrom, valueTo);
+ } else {
+ anim.setDuration(duration);
+ anim.setValues(valueFrom, valueTo);
+ }
+
+ anim.setStartDelay(startDelay);
+
+ if (a.hasValue(com.android.internal.R.styleable.Animator_repeatCount)) {
+ anim.setRepeatCount(
+ a.getInt(com.android.internal.R.styleable.Animator_repeatCount, 0));
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Animator_repeatMode)) {
+ anim.setRepeatMode(
+ a.getInt(com.android.internal.R.styleable.Animator_repeatMode,
+ Animator.RESTART));
+ }
+ if (evaluator != null) {
+ anim.setEvaluator(evaluator);
+ }
+
+ final int resID =
+ a.getResourceId(com.android.internal.R.styleable.Animator_interpolator, 0);
+ if (resID > 0) {
+ anim.setInterpolator(AnimationUtils.loadInterpolator(context, resID));
+ }
+ a.recycle();
+
+ return anim;
+ }
+}
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index eca5f0d..717fc0a 100755
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -17,11 +17,9 @@
package android.animation;
import android.content.Context;
-import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.util.AttributeSet;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -70,15 +68,6 @@
private static final int SEEKED = 4; // Seeked to some time value
/**
- * Enum values used in XML attributes to indicate the value for mValueType
- */
- private static final int VALUE_TYPE_FLOAT = 0;
- private static final int VALUE_TYPE_INT = 1;
- private static final int VALUE_TYPE_DOUBLE = 2;
- private static final int VALUE_TYPE_COLOR = 3;
- private static final int VALUE_TYPE_CUSTOM = 4;
-
- /**
* Internal variables
* NOTE: This object implements the clone() method, making a deep copy of any referenced
* objects. As other non-trivial fields are added to this class, make sure to add logic
@@ -209,11 +198,6 @@
HashMap<String, PropertyValuesHolder> mValuesMap;
/**
- * The type of the values, as determined by the valueFrom/valueTo properties.
- */
- Class mValueType;
-
- /**
* Public constants
*/
@@ -234,76 +218,13 @@
public static final int INFINITE = -1;
/**
- * Creates a new animation whose parameters come from the specified context and
- * attributes set.
- *
- * @param context the application environment
- * @param attrs the set of attributes holding the animation parameters
+ * Creates a new Animator object. This default constructor is primarily for
+ * use internally; the other constructors which take parameters are more generally
+ * useful.
*/
- public Animator(Context context, AttributeSet attrs) {
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Animator);
-
- mDuration = (long) a.getInt(com.android.internal.R.styleable.Animator_duration, 0);
-
- mStartDelay = (long) a.getInt(com.android.internal.R.styleable.Animator_startOffset, 0);
-
- final int resID =
- a.getResourceId(com.android.internal.R.styleable.Animator_interpolator, 0);
- if (resID > 0) {
- setInterpolator(AnimationUtils.loadInterpolator(context, resID));
- }
- int valueType = a.getInt(com.android.internal.R.styleable.Animator_valueType,
- VALUE_TYPE_FLOAT);
-
- Object valueFrom = null;
- Object valueTo = null;
-
- switch (valueType) {
- case VALUE_TYPE_FLOAT:
- valueFrom = a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f);
- valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
- mValueType = float.class;
- break;
- case VALUE_TYPE_INT:
- valueFrom = a.getInt(com.android.internal.R.styleable.Animator_valueFrom, 0);
- valueTo = a.getInt(com.android.internal.R.styleable.Animator_valueTo, 0);
- mValueType = int.class;
- break;
- case VALUE_TYPE_DOUBLE:
- valueFrom = (double)
- a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f);
- valueTo = (double)
- a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
- mValueType = double.class;
- break;
- case VALUE_TYPE_COLOR:
- valueFrom = a.getInt(com.android.internal.R.styleable.Animator_valueFrom, 0);
- valueTo = a.getInt(com.android.internal.R.styleable.Animator_valueTo, 0);
- setEvaluator(new RGBEvaluator());
- mValueType = int.class;
- break;
- case VALUE_TYPE_CUSTOM:
- // TODO: How to get an 'Object' value?
- valueFrom = a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f);
- valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
- mValueType = Object.class;
- break;
- }
-
- PropertyValuesHolder valuesHolder = new PropertyValuesHolder("", valueFrom, valueTo);
- mValues = new PropertyValuesHolder[1];
- mValues[0] = valuesHolder;
- mValuesMap = new HashMap<String, PropertyValuesHolder>(1);
- mValuesMap.put("", valuesHolder);
-
- mRepeatCount = a.getInt(com.android.internal.R.styleable.Animator_repeatCount, mRepeatCount);
- mRepeatMode = a.getInt(com.android.internal.R.styleable.Animator_repeatMode, RESTART);
-
- a.recycle();
+ public Animator() {
}
-
/**
* Constructs an Animator object with the specified duration and set of
* values. If the values are a set of PropertyValuesHolder objects, then these objects
@@ -373,6 +294,25 @@
mInitialized = true;
}
+
+ /**
+ * Sets the length of the animation.
+ *
+ * @param duration The length of the animation, in milliseconds.
+ */
+ public void setDuration(long duration) {
+ mDuration = duration;
+ }
+
+ /**
+ * Gets the length of the animation.
+ *
+ * @return The length of the animation, in milliseconds.
+ */
+ public long getDuration() {
+ return mDuration;
+ }
+
/**
* Sets the position of the animation to the specified point in time. This time should
* be between 0 and the total duration of the animation, including any repetition. If
@@ -723,12 +663,13 @@
* @param playBackwards Whether the Animator should start playing in reverse.
*/
private void start(boolean playBackwards) {
+ mPlayingBackwards = playBackwards;
if ((mStartDelay == 0) && (Thread.currentThread() == Looper.getMainLooper().getThread())) {
// This sets the initial value of the animation, prior to actually starting it running
setCurrentPlayTime(getCurrentPlayTime());
}
- mPlayingBackwards = playBackwards;
mPlayingState = STOPPED;
+ mStartedDelay = false;
sPendingAnimations.add(this);
if (sAnimationHandler == null) {
sAnimationHandler = new AnimationHandler();
@@ -738,15 +679,6 @@
sAnimationHandler.sendEmptyMessage(ANIMATION_START);
}
- /**
- * Returns the duration that this animation will run for.
- *
- * @return The length in time of the animation, in milliseconds.
- */
- public long getDuration() {
- return mDuration;
- }
-
@Override
public void start() {
start(false);
@@ -768,15 +700,21 @@
@Override
public void end() {
+ if (!sAnimations.contains(this) &&
+ (Thread.currentThread() == Looper.getMainLooper().getThread())) {
+ // Special case if the animation has not yet started. Set the end value.
+ long endTime = mDuration;
+ if (mRepeatCount > 0) {
+ endTime += mRepeatCount * mDuration;
+ }
+ setCurrentPlayTime(endTime);
+ }
// Just set the ENDED flag - this causes the animation to end the next time a frame
// is processed.
mPlayingState = ENDED;
}
- /**
- * Returns whether this Animator is currently running (having been started and not yet ended).
- * @return Wehther the Animator is running.
- */
+ @Override
public boolean isRunning() {
return mPlayingState == RUNNING;
}
@@ -806,6 +744,7 @@
*/
private void endAnimation() {
sAnimations.remove(this);
+ mPlayingState = STOPPED;
if (mListeners != null) {
ArrayList<AnimatableListener> tmpListeners =
(ArrayList<AnimatableListener>) mListeners.clone();
@@ -813,7 +752,6 @@
listener.onAnimationEnd(this);
}
}
- mPlayingState = STOPPED;
}
/**
diff --git a/core/java/android/animation/PropertyAnimator.java b/core/java/android/animation/PropertyAnimator.java
index 022ca7d..8a6edcc 100644
--- a/core/java/android/animation/PropertyAnimator.java
+++ b/core/java/android/animation/PropertyAnimator.java
@@ -16,9 +16,6 @@
package android.animation;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
import android.util.Log;
import java.lang.reflect.Method;
@@ -81,25 +78,6 @@
}
/**
- * Creates a new animation whose parameters come from the specified context and
- * attributes set.
- *
- * @param context the application environment
- * @param attrs the set of attributes holding the animation parameters
- */
- public PropertyAnimator(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.PropertyAnimator);
-
- setPropertyName(a.getString(
- com.android.internal.R.styleable.PropertyAnimator_propertyName));
-
-
- a.recycle();
- }
- /**
* Determine the setter or getter function using the JavaBeans convention of setFoo or
* getFoo for a property named 'foo'. This function figures out what the name of the
* function should be and uses reflection to find the Method with that name on the
@@ -130,6 +108,14 @@
}
/**
+ * Creates a new PropertyAnimator object. This default constructor is primarily for
+ * use internally; the other constructors which take parameters are more generally
+ * useful.
+ */
+ public PropertyAnimator() {
+ }
+
+ /**
* A constructor that takes a single property name and set of values. This constructor is
* used in the simple case of animating a single property.
*
diff --git a/core/java/android/animation/Sequencer.java b/core/java/android/animation/Sequencer.java
index 7749429..63ec940 100644
--- a/core/java/android/animation/Sequencer.java
+++ b/core/java/android/animation/Sequencer.java
@@ -233,6 +233,10 @@
@Override
public void end() {
mCanceled = true;
+ if (mSortedNodes.size() != mNodes.size()) {
+ // hasn't been started yet - sort the nodes now, then end them
+ sortNodes();
+ }
if (mSortedNodes.size() > 0) {
for (Node node : mSortedNodes) {
node.animation.end();
@@ -241,6 +245,21 @@
}
/**
+ * Returns true if any of the child animations of this Sequencer have been started and have not
+ * yet ended.
+ * @return Whether this Sequencer has been started and has not yet ended.
+ */
+ @Override
+ public boolean isRunning() {
+ for (Node node : mNodes) {
+ if (node.animation.isRunning()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* {@inheritDoc}
*
* <p>Starting this <code>Sequencer</code> will, in turn, start the animations for which
@@ -467,14 +486,10 @@
public void onAnimationEnd(Animatable animation) {
animation.removeListener(this);
mPlayingSet.remove(animation);
- Node animNode = mSequencer.mNodeMap.get(animation);
- animNode.done = true;
ArrayList<Node> sortedNodes = mSequencer.mSortedNodes;
- int numNodes = sortedNodes.size();
- int nodeIndex = sortedNodes.indexOf(animNode);
boolean allDone = true;
- for (int i = nodeIndex + 1; i < numNodes; ++i) {
- if (!sortedNodes.get(i).done) {
+ for (Node node : sortedNodes) {
+ if (node.animation.isRunning()) {
allDone = false;
break;
}
@@ -558,7 +573,6 @@
}
}
}
- node.done = false; // also reset done flag
}
}
}
@@ -626,13 +640,6 @@
public ArrayList<Node> nodeDependents = null;
/**
- * Flag indicating whether the animation in this node is finished. This flag
- * is used by Sequencer to check, as each animation ends, whether all child animations
- * are done and it's time to send out an end event for the entire Sequencer.
- */
- public boolean done = false;
-
- /**
* Constructs the Node with the animation that it encapsulates. A Node has no
* dependencies by default; dependencies are added via the addDependency()
* method.
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index a93184d..73e8d31 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1248,8 +1248,9 @@
case IS_USER_A_MONKEY_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- reply.writeInt(isUserAMonkey() ? 1 : 0);
+ boolean areThey = isUserAMonkey();
reply.writeNoException();
+ reply.writeInt(areThey ? 1 : 0);
return true;
}
@@ -1263,8 +1264,9 @@
case IS_IMMERSIVE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
- reply.writeInt(isImmersive(token) ? 1 : 0);
+ boolean isit = isImmersive(token);
reply.writeNoException();
+ reply.writeInt(isit ? 1 : 0);
return true;
}
@@ -1279,8 +1281,9 @@
case IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- reply.writeInt(isTopActivityImmersive() ? 1 : 0);
+ boolean isit = isTopActivityImmersive();
reply.writeNoException();
+ reply.writeInt(isit ? 1 : 0);
return true;
}
@@ -1294,6 +1297,40 @@
reply.writeNoException();
return true;
}
+
+ case NEW_URI_PERMISSION_OWNER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ String name = data.readString();
+ IBinder perm = newUriPermissionOwner(name);
+ reply.writeNoException();
+ reply.writeStrongBinder(perm);
+ return true;
+ }
+
+ case GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder owner = data.readStrongBinder();
+ int fromUid = data.readInt();
+ String targetPkg = data.readString();
+ Uri uri = Uri.CREATOR.createFromParcel(data);
+ int mode = data.readInt();
+ grantUriPermissionFromOwner(owner, fromUid, targetPkg, uri, mode);
+ reply.writeNoException();
+ return true;
+ }
+
+ case REVOKE_URI_PERMISSION_FROM_OWNER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder owner = data.readStrongBinder();
+ Uri uri = null;
+ if (data.readInt() != 0) {
+ Uri.CREATOR.createFromParcel(data);
+ }
+ int mode = data.readInt();
+ revokeUriPermissionFromOwner(owner, uri, mode);
+ reply.writeNoException();
+ return true;
+ }
case DUMP_HEAP_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
@@ -2854,8 +2891,8 @@
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
mRemote.transact(IS_IMMERSIVE_TRANSACTION, data, reply, 0);
- boolean res = reply.readInt() == 1;
reply.readException();
+ boolean res = reply.readInt() == 1;
data.recycle();
reply.recycle();
return res;
@@ -2867,8 +2904,8 @@
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
mRemote.transact(IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION, data, reply, 0);
- boolean res = reply.readInt() == 1;
reply.readException();
+ boolean res = reply.readInt() == 1;
data.recycle();
reply.recycle();
return res;
@@ -2889,6 +2926,55 @@
reply.recycle();
}
+ public IBinder newUriPermissionOwner(String name)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(name);
+ mRemote.transact(NEW_URI_PERMISSION_OWNER_TRANSACTION, data, reply, 0);
+ reply.readException();
+ IBinder res = reply.readStrongBinder();
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+
+ public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
+ Uri uri, int mode) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(owner);
+ data.writeInt(fromUid);
+ data.writeString(targetPkg);
+ uri.writeToParcel(data, 0);
+ data.writeInt(mode);
+ mRemote.transact(GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ public void revokeUriPermissionFromOwner(IBinder owner, Uri uri,
+ int mode) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(owner);
+ if (uri != null) {
+ data.writeInt(1);
+ uri.writeToParcel(data, 0);
+ } else {
+ data.writeInt(0);
+ }
+ data.writeInt(mode);
+ mRemote.transact(REVOKE_URI_PERMISSION_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
public boolean dumpHeap(String process, boolean managed,
String path, ParcelFileDescriptor fd) throws RemoteException {
Parcel data = Parcel.obtain();
@@ -2910,6 +2996,6 @@
data.recycle();
return res;
}
-
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index e34bad2..fee95aa 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2878,6 +2878,11 @@
}
}
+ public void startCommit() {
+ // TODO: implement
+ commit();
+ }
+
public boolean commit() {
boolean returnValue;
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index f190d0d..c63233e 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -17,6 +17,7 @@
package android.app;
import android.animation.Animatable;
+import android.animation.AnimatableInflater;
import android.animation.PropertyAnimator;
import android.animation.Sequencer;
import android.content.res.TypedArray;
@@ -31,7 +32,6 @@
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.view.animation.AnimationUtils;
import java.util.ArrayList;
@@ -257,7 +257,7 @@
}
if (fragment.mNextAnim != 0) {
- Animatable anim = AnimationUtils.loadAnimator(mActivity, fragment.mNextAnim);
+ Animatable anim = AnimatableInflater.loadAnimatable(mActivity, fragment.mNextAnim);
if (anim != null) {
return anim;
}
@@ -288,7 +288,7 @@
return null;
}
- return AnimationUtils.loadAnimator(mActivity, anim);
+ return AnimatableInflater.loadAnimatable(mActivity, anim);
}
void moveToState(Fragment f, int newState, int transit, int transitionStyle) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 5514582..901f117 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -317,6 +317,12 @@
public void crashApplication(int uid, int initialPid, String packageName,
String message) throws RemoteException;
+
+ public IBinder newUriPermissionOwner(String name) throws RemoteException;
+ public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
+ Uri uri, int mode) throws RemoteException;
+ public void revokeUriPermissionFromOwner(IBinder owner, Uri uri,
+ int mode) throws RemoteException;
// Cause the specified process to dump the specified heap.
public boolean dumpHeap(String process, boolean managed, String path,
@@ -528,5 +534,8 @@
int SET_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+111;
int IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+112;
int CRASH_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+113;
- int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+114;
+ int NEW_URI_PERMISSION_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+114;
+ int GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+115;
+ int REVOKE_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+116;
+ int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+117;
}
diff --git a/core/java/android/content/ContentValues.java b/core/java/android/content/ContentValues.java
index e6dedc13..ce047f6 100644
--- a/core/java/android/content/ContentValues.java
+++ b/core/java/android/content/ContentValues.java
@@ -497,6 +497,10 @@
return (ArrayList<String>) mValues.get(key);
}
+ /**
+ * Returns a string containing a concise, human-readable description of this object.
+ * @return a printable representation of this object.
+ */
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index 5847216..6ee716a 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -163,14 +163,47 @@
* {@link SharedPreferences} object it is editing. This atomically
* performs the requested modifications, replacing whatever is currently
* in the SharedPreferences.
- *
+ *
* <p>Note that when two editors are modifying preferences at the same
* time, the last one to call commit wins.
- *
+ *
+ * <p>If you don't care about the return value and you're
+ * using this from your application's main thread, consider
+ * using {@link #startCommit} instead.
+ *
* @return Returns true if the new values were successfully written
* to persistent storage.
*/
boolean commit();
+
+ /**
+ * Commit your preferences changes back from this Editor to the
+ * {@link SharedPreferences} object it is editing. This atomically
+ * performs the requested modifications, replacing whatever is currently
+ * in the SharedPreferences.
+ *
+ * <p>Note that when two editors are modifying preferences at the same
+ * time, the last one to call commit wins.
+ *
+ * <p>Unlike {@link #commit}, which writes its preferences out
+ * to persistent storage synchronously, {@link #startCommit}
+ * commits its changes to the in-memory
+ * {@link SharedPreferences} immediately but starts an
+ * asynchronous commit to disk and you won't be notified of
+ * any failures. If another editor on this
+ * {@link SharedPreferences} does a regular {@link #commit}
+ * while a {@link #startCommit} is still outstanding, the
+ * {@link #commit} will block until all async commits are
+ * completed as well as the commit itself.
+ *
+ * <p>If you call this from an {@link android.app.Activity},
+ * the base class will wait for any async commits to finish in
+ * its {@link android.app.Activity#onPause}.</p>
+ *
+ * @return Returns true if the new values were successfully written
+ * to persistent storage.
+ */
+ void startCommit();
}
/**
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 97921fe..0068724 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -34,11 +34,19 @@
import java.util.List;
/**
+ * <p>
* SensorManager lets you access the device's {@link android.hardware.Sensor
* sensors}. Get an instance of this class by calling
* {@link android.content.Context#getSystemService(java.lang.String)
* Context.getSystemService()} with the argument
* {@link android.content.Context#SENSOR_SERVICE}.
+ * </p>
+ * <p>
+ * Always make sure to disable sensors you don't need, especially when your
+ * activity is paused. Failing to do so can drain the battery in just a few
+ * hours. Note that the system will <i>not</i> disable sensors automatically when
+ * the screen turns off.
+ * </p>
*
* <pre class="prettyprint">
* public class SensorActivity extends Activity, implements SensorEventListener {
@@ -48,13 +56,22 @@
* public SensorActivity() {
* mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
* mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ * }
+ *
+ * protected void onResume() {
+ * super.onResume();
* mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
* }
*
+ * protected void onPause() {
+ * super.onPause();
+ * mSensorManager.unregisterListener(this);
+ * }
+ *
* public void onAccuracyChanged(Sensor sensor, int accuracy) {
* }
*
- * public abstract void onSensorChanged(SensorEvent event) {
+ * public void onSensorChanged(SensorEvent event) {
* }
* }
* </pre>
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 227d94d..60ccdaf 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -322,6 +322,8 @@
private static final int MICRO_KIND = 3;
private static final String[] PROJECTION = new String[] {_ID, MediaColumns.DATA};
static final int DEFAULT_GROUP_ID = 0;
+ private static final Object sThumbBufLock = new Object();
+ private static byte[] sThumbBuf;
private static Bitmap getMiniThumbFromFile(Cursor c, Uri baseUri, ContentResolver cr, BitmapFactory.Options options) {
Bitmap bitmap = null;
@@ -397,11 +399,15 @@
long magic = thumbFile.getMagic(origId);
if (magic != 0) {
if (kind == MICRO_KIND) {
- byte[] data = new byte[MiniThumbFile.BYTES_PER_MINTHUMB];
- if (thumbFile.getMiniThumbFromFile(origId, data) != null) {
- bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- if (bitmap == null) {
- Log.w(TAG, "couldn't decode byte array.");
+ synchronized (sThumbBufLock) {
+ if (sThumbBuf == null) {
+ sThumbBuf = new byte[MiniThumbFile.BYTES_PER_MINTHUMB];
+ }
+ if (thumbFile.getMiniThumbFromFile(origId, sThumbBuf) != null) {
+ bitmap = BitmapFactory.decodeByteArray(sThumbBuf, 0, sThumbBuf.length);
+ if (bitmap == null) {
+ Log.w(TAG, "couldn't decode byte array.");
+ }
}
}
return bitmap;
@@ -427,11 +433,15 @@
// Assuming thumbnail has been generated, at least original image exists.
if (kind == MICRO_KIND) {
- byte[] data = new byte[MiniThumbFile.BYTES_PER_MINTHUMB];
- if (thumbFile.getMiniThumbFromFile(origId, data) != null) {
- bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- if (bitmap == null) {
- Log.w(TAG, "couldn't decode byte array.");
+ synchronized (sThumbBufLock) {
+ if (sThumbBuf == null) {
+ sThumbBuf = new byte[MiniThumbFile.BYTES_PER_MINTHUMB];
+ }
+ if (thumbFile.getMiniThumbFromFile(origId, sThumbBuf) != null) {
+ bitmap = BitmapFactory.decodeByteArray(sThumbBuf, 0, sThumbBuf.length);
+ if (bitmap == null) {
+ Log.w(TAG, "couldn't decode byte array.");
+ }
}
}
} else if (kind == MINI_KIND) {
diff --git a/core/java/android/provider/Mtp.java b/core/java/android/provider/Mtp.java
index bc764ac..26aa7d8 100644
--- a/core/java/android/provider/Mtp.java
+++ b/core/java/android/provider/Mtp.java
@@ -311,9 +311,12 @@
// Object properties we support
public static final int PROPERTY_STORAGE_ID = 0xDC01;
public static final int PROPERTY_OBJECT_FORMAT = 0xDC02;
+ public static final int PROPERTY_PROTECTION_STATUS = 0xDC03;
public static final int PROPERTY_OBJECT_SIZE = 0xDC04;
public static final int PROPERTY_OBJECT_FILE_NAME = 0xDC07;
+ public static final int PROPERTY_DATE_MODIFIED = 0xDC09;
public static final int PROPERTY_PARENT_OBJECT = 0xDC0B;
+ public static final int PROPERTY_PERSISTENT_UID = 0xDC41;
/**
* Object is not protected. It may be modified and deleted, and its properties
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 0e3522e..2f7482c 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -75,7 +75,7 @@
}
}
tl = new TextLine();
- Log.e("TLINE", "new: " + tl);
+ Log.v("TLINE", "new: " + tl);
return tl;
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 32d8123..42e3641 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -53,8 +53,10 @@
/**
* Destroys the hardware rendering context.
+ *
+ * @param full If true, destroys all associated resources.
*/
- abstract void destroy();
+ abstract void destroy(boolean full);
/**
* Initializes the hardware renderer for the specified surface.
@@ -187,7 +189,7 @@
}
/**
- * Checks for OpenGL errors. If an error has occured, {@link #destroy()}
+ * Checks for OpenGL errors. If an error has occured, {@link #destroy(boolean)}
* is invoked and the requested flag is turned off. The error code is
* also logged as a warning.
*/
@@ -197,7 +199,7 @@
if (error != EGL10.EGL_SUCCESS) {
// something bad has happened revert to
// normal rendering.
- destroy();
+ destroy(true);
if (error != EGL11.EGL_CONTEXT_LOST) {
// we'll try again if it was context lost
setRequested(false);
@@ -217,13 +219,12 @@
if (mGl != null) {
int err = sEgl.eglGetError();
if (err != EGL10.EGL_SUCCESS) {
- destroy();
+ destroy(true);
setRequested(false);
} else {
- if (mCanvas != null) {
- destroyCanvas();
+ if (mCanvas == null) {
+ mCanvas = createCanvas();
}
- mCanvas = createCanvas();
if (mCanvas != null) {
setEnabled(true);
} else {
@@ -237,11 +238,6 @@
return false;
}
- private void destroyCanvas() {
- mCanvas.destroy();
- mCanvas = null;
- }
-
abstract GLES20Canvas createCanvas();
void initializeEgl() {
@@ -341,16 +337,16 @@
}
@Override
- void destroy() {
+ void destroy(boolean full) {
+ if (full && mCanvas != null) {
+ mCanvas.destroy();
+ mCanvas = null;
+ }
+
if (!isEnabled() || mDestroyed) return;
mDestroyed = true;
- checkCurrent();
- // Destroy the Canvas first in case it needs to use a GL context
- // to perform its cleanup.
- destroyCanvas();
-
sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
@@ -358,12 +354,6 @@
mEglSurface = null;
mGl = null;
- // mEgl.eglDestroyContext(mEglDisplay, mEglContext);
- // mEglContext = null;
- // mEgl.eglTerminate(mEglDisplay);
- // mEgl = null;
- // mEglDisplay = null;
-
setEnabled(false);
}
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 479e757..458274f 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -349,6 +349,7 @@
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
synchronized (mConstructorArgs) {
final AttributeSet attrs = Xml.asAttributeSet(parser);
+ Context lastContext = (Context)mConstructorArgs[0];
mConstructorArgs[0] = mContext;
View result = root;
@@ -433,6 +434,10 @@
+ ": " + e.getMessage());
ex.initCause(e);
throw ex;
+ } finally {
+ // Don't retain static reference on context.
+ mConstructorArgs[0] = lastContext;
+ mConstructorArgs[1] = null;
}
return result;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b565fc6..616128d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -262,7 +262,8 @@
* <ul>
* <li>Define a Button in the layout file and assign it a unique ID.
* <pre>
- * <Button id="@+id/my_button"
+ * <Button
+ * android:id="@+id/my_button"
* android:layout_width="wrap_content"
* android:layout_height="wrap_content"
* android:text="@string/my_button_text"/>
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 402443c..7b6991f 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -1138,22 +1138,24 @@
final View captureView = findView(root, parameter);
Bitmap b = performViewCapture(captureView, false);
-
- if (b != null) {
- BufferedOutputStream out = null;
- try {
- out = new BufferedOutputStream(clientStream, 32 * 1024);
- b.compress(Bitmap.CompressFormat.PNG, 100, out);
- out.flush();
- } finally {
- if (out != null) {
- out.close();
- }
- b.recycle();
- }
- } else {
+
+ if (b == null) {
Log.w("View", "Failed to create capture bitmap!");
- clientStream.close();
+ // Send an empty one so that it doesn't get stuck waiting for
+ // something.
+ b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+ }
+
+ BufferedOutputStream out = null;
+ try {
+ out = new BufferedOutputStream(clientStream, 32 * 1024);
+ b.compress(Bitmap.CompressFormat.PNG, 100, out);
+ out.flush();
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ b.recycle();
}
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 3678684..9770313 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -970,7 +970,12 @@
mMotionTarget = null;
}
- return target.dispatchTouchEvent(ev);
+ if (target.dispatchTouchEvent(ev)) {
+ return true;
+ } else {
+ ev.setLocation(xf, yf);
+ }
+ return false;
}
/**
@@ -1006,7 +1011,12 @@
// There are many subtle interactions in touch event dispatch; change at your own risk.
child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
ev.offsetLocation(localX - x, localY - y);
- return child.dispatchTouchEvent(ev);
+ if (child.dispatchTouchEvent(ev)) {
+ return true;
+ } else {
+ ev.offsetLocation(x - localX, y - localY);
+ return false;
+ }
}
return false;
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 5999aba..a91d2bd 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -469,7 +469,9 @@
if (attrs != null &&
(attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) {
final boolean translucent = attrs.format != PixelFormat.OPAQUE;
- destroyHardwareRenderer();
+ if (mHwRenderer != null) {
+ mHwRenderer.destroy(true);
+ }
mHwRenderer = HardwareRenderer.createGlRenderer(2, translucent);
}
}
@@ -678,7 +680,9 @@
attachInfo.mWindowVisibility = viewVisibility;
host.dispatchWindowVisibilityChanged(viewVisibility);
if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
- destroyHardwareRenderer();
+ if (mHwRenderer != null) {
+ mHwRenderer.destroy(false);
+ }
}
if (viewVisibility == View.GONE) {
// After making a window gone, we will count it as being
@@ -1597,9 +1601,11 @@
mAttachInfo.mRootView = null;
mAttachInfo.mSurface = null;
- destroyHardwareRenderer();
- mHwRenderer = null;
-
+ if (mHwRenderer != null) {
+ mHwRenderer.destroy(true);
+ mHwRenderer = null;
+ }
+
mSurface.release();
if (mInputChannel != null) {
@@ -1624,12 +1630,6 @@
}
}
- private void destroyHardwareRenderer() {
- if (mHwRenderer != null) {
- mHwRenderer.destroy();
- }
- }
-
void updateConfiguration(Configuration config, boolean force) {
if (DEBUG_CONFIGURATION) Log.v(TAG,
"Applying new config to window "
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 8e4cf67..c090f8e 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -16,12 +16,6 @@
package android.view.animation;
-import android.animation.Animatable;
-import android.animation.Animator;
-import android.animation.PropertyAnimator;
-import android.animation.Sequencer;
-import android.content.res.TypedArray;
-import android.util.TypedValue;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -33,7 +27,6 @@
import android.os.SystemClock;
import java.io.IOException;
-import java.util.ArrayList;
/**
* Defines common utilities for working with animations.
@@ -92,42 +85,6 @@
}
}
- /**
- * Loads an {@link Animation} object from a resource
- *
- * @param context Application context used to access resources
- * @param id The resource id of the animation to load
- * @return The animation object reference by the specified id
- * @throws NotFoundException when the animation cannot be loaded
- */
- public static Animatable loadAnimator(Context context, int id)
- throws NotFoundException {
-
- XmlResourceParser parser = null;
- try {
- parser = context.getResources().getAnimation(id);
- return createAnimatableFromXml(context, parser);
- } catch (XmlPullParserException ex) {
- NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } catch (IOException ex) {
- NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } finally {
- if (parser != null) parser.close();
- }
- }
-
- private static Animatable createAnimatableFromXml(Context c, XmlPullParser parser)
- throws XmlPullParserException, IOException {
-
- return createAnimatableFromXml(c, parser, Xml.asAttributeSet(parser), null, 0);
- }
-
private static Animation createAnimationFromXml(Context c, XmlPullParser parser)
throws XmlPullParserException, IOException {
@@ -176,66 +133,6 @@
}
- private static Animatable createAnimatableFromXml(Context c, XmlPullParser parser,
- AttributeSet attrs, Sequencer parent, int sequenceOrdering)
- throws XmlPullParserException, IOException {
-
- Animatable anim = null;
- ArrayList<Animatable> childAnims = null;
-
- // Make sure we are on a start tag.
- int type;
- int depth = parser.getDepth();
-
- while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
- && type != XmlPullParser.END_DOCUMENT) {
-
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
-
- String name = parser.getName();
-
- if (name.equals("property")) {
- anim = new PropertyAnimator(c, attrs);
- } else if (name.equals("animator")) {
- anim = new Animator(c, attrs);
- } else if (name.equals("sequencer")) {
- anim = new Sequencer();
- TypedArray a = c.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.Sequencer);
- int ordering = a.getInt(com.android.internal.R.styleable.Sequencer_ordering,
- TOGETHER);
- createAnimatableFromXml(c, parser, attrs, (Sequencer) anim, ordering);
- a.recycle();
- } else {
- throw new RuntimeException("Unknown animator name: " + parser.getName());
- }
-
- if (parent != null) {
- if (childAnims == null) {
- childAnims = new ArrayList<Animatable>();
- }
- childAnims.add(anim);
- }
- }
- if (parent != null && childAnims != null) {
- Animatable[] animsArray = new Animatable[childAnims.size()];
- int index = 0;
- for (Animatable a : childAnims) {
- animsArray[index++] = a;
- }
- if (sequenceOrdering == TOGETHER) {
- parent.playTogether(animsArray);
- } else {
- parent.playSequentially(animsArray);
- }
- }
-
- return anim;
-
- }
-
public static LayoutAnimationController loadLayoutAnimation(Context context, int id)
throws NotFoundException {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 5d9ab90..682319f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1376,6 +1376,7 @@
SslCertificate.saveState(mCertificate));
}
outState.putBoolean("privateBrowsingEnabled", isPrivateBrowsingEnabled());
+ mZoomManager.saveZoomState(outState);
return list;
}
@@ -1542,6 +1543,7 @@
if (inState.getBoolean("privateBrowsingEnabled")) {
getSettings().setPrivateBrowsingEnabled(true);
}
+ mZoomManager.restoreZoomState(inState);
// Remove all pending messages because we are restoring previous
// state.
mWebViewCore.removeMessages();
@@ -3355,7 +3357,8 @@
setUpSelect();
if (mNativeClass != 0 && nativeWordSelection(x, y)) {
nativeSetExtendSelection();
- getWebChromeClient().onSelectionStart(this);
+ WebChromeClient client = getWebChromeClient();
+ if (client != null) client.onSelectionStart(this);
return true;
}
notifySelectDialogDismissed();
@@ -4088,7 +4091,7 @@
return true;
}
clearTextEntry();
- nativeSetFollowedLink(true);
+ nativeShowCursorTimed();
if (!mCallbackProxy.uiOverrideUrlLoading(nativeCursorText())) {
mWebViewCore.sendMessage(EventHub.CLICK, data.mFrame,
nativeCursorNodePointer());
@@ -4175,7 +4178,8 @@
*/
public void selectionDone() {
if (mSelectingText) {
- getWebChromeClient().onSelectionDone(this);
+ WebChromeClient client = getWebChromeClient();
+ if (client != null) client.onSelectionDone(this);
invalidate(); // redraw without selection
notifySelectDialogDismissed();
}
@@ -7327,9 +7331,9 @@
private native void nativeSetExtendSelection();
private native void nativeSetFindIsEmpty();
private native void nativeSetFindIsUp(boolean isUp);
- private native void nativeSetFollowedLink(boolean followed);
private native void nativeSetHeightCanMeasure(boolean measure);
private native void nativeSetBaseLayer(int layer);
+ private native void nativeShowCursorTimed();
private native void nativeReplaceBaseContent(int content);
private native void nativeCopyBaseContentToPicture(Picture pict);
private native boolean nativeHasContent();
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index b6c8e47..e78c8b7 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -23,6 +23,7 @@
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.Handler;
import android.os.Looper;
import android.os.Parcel;
@@ -323,15 +324,13 @@
return null;
}
- private LayoutParams createOrReuseLayoutParams(View v) {
+ LayoutParams createOrReuseLayoutParams(View v) {
final ViewGroup.LayoutParams currentLp = v.getLayoutParams();
- if (currentLp instanceof LayoutParams) {
+ if (currentLp instanceof ViewGroup.LayoutParams) {
LayoutParams lp = (LayoutParams) currentLp;
- lp.setHorizontalOffset(0);
- lp.setVerticalOffset(0);
return lp;
}
- return new LayoutParams(v);
+ return new ViewGroup.LayoutParams(0, 0);
}
void showOnly(int childIndex, boolean animate, boolean onLayout) {
@@ -472,10 +471,9 @@
int childRight = mPaddingLeft + child.getMeasuredWidth();
int childBottom = mPaddingTop + child.getMeasuredHeight();
- LayoutParams lp = (LayoutParams) child.getLayoutParams();
- child.layout(mPaddingLeft + lp.horizontalOffset, mPaddingTop + lp.verticalOffset,
- childRight + lp.horizontalOffset, childBottom + lp.verticalOffset);
+ child.layout(mPaddingLeft, mPaddingTop,
+ childRight, childBottom);
}
mDataChanged = false;
}
@@ -738,102 +736,4 @@
setAdapter(mRemoteViewsAdapter);
}
}
-
- private final Rect dirtyRect = new Rect();
- @Override
- public void removeViewInLayout(View view) {
- // TODO: need to investigate this block a bit more
- // and perhaps fix some other invalidations issues.
- View parent = null;
- view.setVisibility(INVISIBLE);
- if (view.getLayoutParams() instanceof LayoutParams) {
- LayoutParams lp = (LayoutParams) view.getLayoutParams();
- parent = lp.getParentAndDirtyRegion(dirtyRect);
- }
-
- super.removeViewInLayout(view);
-
- if (parent != null)
- parent.invalidate(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom);
- }
-
- static class LayoutParams extends ViewGroup.LayoutParams {
- int horizontalOffset;
- int verticalOffset;
- View mView;
-
- LayoutParams(View view) {
- super(0, 0);
- horizontalOffset = 0;
- verticalOffset = 0;
- mView = view;
- }
-
- LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
- horizontalOffset = 0;
- verticalOffset = 0;
- }
-
- private Rect parentRect = new Rect();
- void invalidateGlobalRegion(View v, Rect r) {
- View p = v;
- boolean firstPass = true;
- parentRect.set(0, 0, 0, 0);
- while (p.getParent() != null && p.getParent() instanceof View
- && !parentRect.contains(r)) {
- if (!firstPass) r.offset(p.getLeft() - p.getScrollX(), p.getTop() - p.getScrollY());
- firstPass = false;
- p = (View) p.getParent();
- parentRect.set(p.getLeft() - p.getScrollX(), p.getTop() - p.getScrollY(),
- p.getRight() - p.getScrollX(), p.getBottom() - p.getScrollY());
- }
- p.invalidate(r.left, r.top, r.right, r.bottom);
- }
-
- public View getParentAndDirtyRegion(Rect globalRect) {
- globalRect.set(mView.getLeft(), mView.getTop(), mView.getRight(), mView.getBottom());
- View p = mView;
- boolean firstPass = true;
- parentRect.set(0, 0, 0, 0);
- while (p.getParent() != null && p.getParent() instanceof View
- && !parentRect.contains(globalRect)) {
- if (!firstPass) {
- globalRect.offset(p.getLeft() - p.getScrollX(), p.getTop() - p.getScrollY());
- }
-
- firstPass = false;
- p = (View) p.getParent();
- parentRect.set(p.getLeft() - p.getScrollX(), p.getTop() - p.getScrollY(),
- p.getRight() - p.getScrollX(), p.getBottom() - p.getScrollY());
- }
- return p;
- }
-
- private Rect invalidateRect = new Rect();
- // This is public so that PropertyAnimator can access it
- public void setVerticalOffset(int newVerticalOffset) {
- int offsetDelta = newVerticalOffset - verticalOffset;
- verticalOffset = newVerticalOffset;
- if (mView != null) {
- mView.requestLayout();
- int top = Math.min(mView.getTop() + offsetDelta, mView.getTop());
- int bottom = Math.max(mView.getBottom() + offsetDelta, mView.getBottom());
- invalidateRect.set(mView.getLeft(), top, mView.getRight(), bottom);
- invalidateGlobalRegion(mView, invalidateRect);
- }
- }
-
- public void setHorizontalOffset(int newHorizontalOffset) {
- int offsetDelta = newHorizontalOffset - horizontalOffset;
- horizontalOffset = newHorizontalOffset;
- if (mView != null) {
- mView.requestLayout();
- int left = Math.min(mView.getLeft() + offsetDelta, mView.getLeft());
- int right = Math.max(mView.getRight() + offsetDelta, mView.getRight());
- invalidateRect.set(left, mView.getTop(), right, mView.getBottom());
- invalidateGlobalRegion(mView, invalidateRect);
- }
- }
- }
}
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index c3e8838..b460adb 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -27,6 +27,7 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
@@ -66,8 +67,6 @@
private static final float SLIDE_UP_RATIO = 0.7f;
private final WeakHashMap<View, Float> mRotations = new WeakHashMap<View, Float>();
- private final WeakHashMap<View, Integer>
- mChildrenToApplyTransformsTo = new WeakHashMap<View, Integer>();
/**
* Sentinel value for no current active pointer.
@@ -90,9 +89,12 @@
private int mMaximumVelocity;
private VelocityTracker mVelocityTracker;
+ private static HolographicHelper sHolographicHelper;
private ImageView mHighlight;
private StackSlider mStackSlider;
private boolean mFirstLayoutHappened = false;
+ private ViewGroup mAncestorContainingAllChildren = null;
+ private int mAncestorHeight = 0;
public StackView(Context context) {
super(context);
@@ -117,9 +119,11 @@
addViewInLayout(mHighlight, -1, new LayoutParams(mHighlight));
mStackSlider = new StackSlider();
- if (!sPaintsInitialized) {
- initializePaints();
+ if (sHolographicHelper == null) {
+ sHolographicHelper = new HolographicHelper();
}
+ setClipChildren(false);
+ setClipToPadding(false);
}
/**
@@ -205,6 +209,7 @@
if (!mRotations.containsKey(child)) {
float rotation = (float) (Math.random()*26 - 13);
mRotations.put(child, rotation);
+ child.setRotation(rotation);
}
// Child has been removed
@@ -212,47 +217,36 @@
if (mRotations.containsKey(child)) {
mRotations.remove(child);
}
- if (mChildrenToApplyTransformsTo.containsKey(child)) {
- mChildrenToApplyTransformsTo.remove(child);
- }
}
-
- // if this view is already in the layout, we need to
- // wait until layout has finished in order to set the
- // pivot point of the rotation (requiring getMeasuredWidth/Height())
- mChildrenToApplyTransformsTo.put(child, relativeIndex);
}
@Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+ }
- if (!mChildrenToApplyTransformsTo.isEmpty()) {
- for (View child: mChildrenToApplyTransformsTo.keySet()) {
- if (mRotations.containsKey(child)) {
- child.setPivotX(child.getMeasuredWidth()/2);
- child.setPivotY(child.getMeasuredHeight()/2);
- child.setRotation(mRotations.get(child));
- }
+ // TODO: right now, this code walks up the hierarchy as far as needed and disables clipping
+ // so that the stack's children can draw outside of the stack's bounds. This is fine within
+ // the context of widgets in the launcher, but is destructive in general, as the clipping
+ // values are not being reset. For this to be a full framework level widget, we will need
+ // framework level support for drawing outside of a parent's bounds.
+ private void disableParentalClipping() {
+ if (mAncestorContainingAllChildren != null) {
+ Log.v(TAG, "Disabling parental clipping.");
+ ViewGroup vg = this;
+ while (vg.getParent() != null && vg.getParent() instanceof ViewGroup) {
+ if (vg == mAncestorContainingAllChildren) break;
+ vg = (ViewGroup) vg.getParent();
+ vg.setClipChildren(false);
+ vg.setClipToPadding(false);
}
- mChildrenToApplyTransformsTo.clear();
}
+ }
+ private void onLayout() {
if (!mFirstLayoutHappened) {
mViewHeight = Math.round(SLIDE_UP_RATIO*getMeasuredHeight());
mSwipeThreshold = Math.round(SWIPE_THRESHOLD_RATIO*mViewHeight);
-
- // TODO: Right now this walks all the way up the view hierarchy and disables
- // ClipChildren and ClipToPadding. We're probably going to want to reset
- // these flags as well.
- setClipChildren(false);
- setClipToPadding(false);
- ViewGroup view = this;
- while (view.getParent() != null && view.getParent() instanceof ViewGroup) {
- view = (ViewGroup) view.getParent();
- view.setClipChildren(false);
- view.setClipToPadding(false);
- }
mFirstLayoutHappened = true;
}
}
@@ -261,7 +255,6 @@
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch(action & MotionEvent.ACTION_MASK) {
-
case MotionEvent.ACTION_DOWN: {
if (mActivePointerId == INVALID_POINTER) {
mInitialX = ev.getX();
@@ -320,7 +313,7 @@
View v = getViewAtRelativeIndex(activeIndex);
if (v == null) return;
- mHighlight.setImageBitmap(createOutline(v));
+ mHighlight.setImageBitmap(sHolographicHelper.createOutline(v));
mHighlight.bringToFront();
v.bringToFront();
mStackSlider.setView(v);
@@ -640,7 +633,6 @@
float getXProgress() {
return mXProgress;
}
-
}
@Override
@@ -649,55 +641,206 @@
setDisplayedChild(mWhichChild);
}
- private static final Paint sHolographicPaint = new Paint();
- private static final Paint sErasePaint = new Paint();
- private static boolean sPaintsInitialized = false;
- private static final float STROKE_WIDTH = 3.0f;
-
- static void initializePaints() {
- sHolographicPaint.setColor(0xff6699ff);
- sHolographicPaint.setFilterBitmap(true);
- sErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
- sErasePaint.setFilterBitmap(true);
- sPaintsInitialized = true;
+ LayoutParams createOrReuseLayoutParams(View v) {
+ final ViewGroup.LayoutParams currentLp = v.getLayoutParams();
+ if (currentLp instanceof LayoutParams) {
+ LayoutParams lp = (LayoutParams) currentLp;
+ lp.setHorizontalOffset(0);
+ lp.setVerticalOffset(0);
+ return lp;
+ }
+ return new LayoutParams(v);
}
- static Bitmap createOutline(View v) {
- if (v.getMeasuredWidth() == 0 || v.getMeasuredHeight() == 0) {
- return null;
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ boolean dataChanged = mDataChanged;
+ if (dataChanged) {
+ handleDataChanged();
+
+ // if the data changes, mWhichChild might be out of the bounds of the adapter
+ // in this case, we reset mWhichChild to the beginning
+ if (mWhichChild >= mAdapter.getCount())
+ mWhichChild = 0;
+
+ showOnly(mWhichChild, true, true);
}
- Bitmap bitmap = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(),
- Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
- float rotationX = v.getRotationX();
- v.setRotationX(0);
- canvas.concat(v.getMatrix());
- v.draw(canvas);
- v.setRotationX(rotationX);
+ int childRight = mPaddingLeft + child.getMeasuredWidth();
+ int childBottom = mPaddingTop + child.getMeasuredHeight();
+ LayoutParams lp = (LayoutParams) child.getLayoutParams();
- Bitmap outlineBitmap = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(),
- Bitmap.Config.ARGB_8888);
- Canvas outlineCanvas = new Canvas(outlineBitmap);
- drawOutline(outlineCanvas, bitmap);
- bitmap.recycle();
- return outlineBitmap;
+ child.layout(mPaddingLeft + lp.horizontalOffset, mPaddingTop + lp.verticalOffset,
+ childRight + lp.horizontalOffset, childBottom + lp.verticalOffset);
+
+ //TODO: temp until fix in View
+ child.setPivotX(child.getMeasuredWidth()/2);
+ child.setPivotY(child.getMeasuredHeight()/2);
+ }
+
+ mDataChanged = false;
+ onLayout();
}
- static void drawOutline(Canvas dest, Bitmap src) {
- dest.drawColor(0, PorterDuff.Mode.CLEAR);
+ class LayoutParams extends ViewGroup.LayoutParams {
+ int horizontalOffset;
+ int verticalOffset;
+ View mView;
- Bitmap mask = src.extractAlpha();
- Matrix id = new Matrix();
+ LayoutParams(View view) {
+ super(0, 0);
+ horizontalOffset = 0;
+ verticalOffset = 0;
+ mView = view;
+ }
- Matrix m = new Matrix();
- float xScale = STROKE_WIDTH*2/(src.getWidth());
- float yScale = STROKE_WIDTH*2/(src.getHeight());
- m.preScale(1+xScale, 1+yScale, src.getWidth()/2, src.getHeight()/2);
- dest.drawBitmap(mask, m, sHolographicPaint);
+ LayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+ horizontalOffset = 0;
+ verticalOffset = 0;
+ }
- dest.drawBitmap(src, id, sErasePaint);
- mask.recycle();
+ private Rect parentRect = new Rect();
+ void invalidateGlobalRegion(View v, Rect r) {
+ View p = v;
+ if (!(v.getParent() != null && v.getParent() instanceof View)) return;
+
+ View gp = (View) v.getParent();
+ boolean firstPass = true;
+ parentRect.set(0, 0, 0, 0);
+ int depth = 0;
+ while (gp.getParent() != null && gp.getParent() instanceof View
+ && !parentRect.contains(r)) {
+ if (!firstPass) {
+ r.offset(p.getLeft() - gp.getScrollX(), p.getTop() - gp.getScrollY());
+ depth++;
+ }
+ firstPass = false;
+ p = (View) p.getParent();
+ gp = (View) p.getParent();
+ parentRect.set(p.getLeft() - gp.getScrollX(), p.getTop() - gp.getScrollY(),
+ p.getRight() - gp.getScrollX(), p.getBottom() - gp.getScrollY());
+ }
+
+ if (depth > mAncestorHeight) {
+ mAncestorContainingAllChildren = (ViewGroup) p;
+ mAncestorHeight = depth;
+ disableParentalClipping();
+ }
+
+ p.invalidate(r.left, r.top, r.right, r.bottom);
+ }
+
+ private Rect invalidateRect = new Rect();
+ private RectF invalidateRectf = new RectF();
+ // This is public so that PropertyAnimator can access it
+ public void setVerticalOffset(int newVerticalOffset) {
+ int offsetDelta = newVerticalOffset - verticalOffset;
+ verticalOffset = newVerticalOffset;
+
+ if (mView != null) {
+ mView.requestLayout();
+ int top = Math.min(mView.getTop() + offsetDelta, mView.getTop());
+ int bottom = Math.max(mView.getBottom() + offsetDelta, mView.getBottom());
+
+ invalidateRectf.set(mView.getLeft(), top, mView.getRight(), bottom);
+
+ float xoffset = -invalidateRectf.left;
+ float yoffset = -invalidateRectf.top;
+ invalidateRectf.offset(xoffset, yoffset);
+ mView.getMatrix().mapRect(invalidateRectf);
+ invalidateRectf.offset(-xoffset, -yoffset);
+ invalidateRect.set((int) Math.floor(invalidateRectf.left),
+ (int) Math.floor(invalidateRectf.top),
+ (int) Math.ceil(invalidateRectf.right),
+ (int) Math.ceil(invalidateRectf.bottom));
+
+ invalidateGlobalRegion(mView, invalidateRect);
+ }
+ }
+
+ public void setHorizontalOffset(int newHorizontalOffset) {
+ int offsetDelta = newHorizontalOffset - horizontalOffset;
+ horizontalOffset = newHorizontalOffset;
+
+ if (mView != null) {
+ mView.requestLayout();
+ int left = Math.min(mView.getLeft() + offsetDelta, mView.getLeft());
+ int right = Math.max(mView.getRight() + offsetDelta, mView.getRight());
+ invalidateRectf.set(left, mView.getTop(), right, mView.getBottom());
+
+ float xoffset = -invalidateRectf.left;
+ float yoffset = -invalidateRectf.top;
+ invalidateRectf.offset(xoffset, yoffset);
+ mView.getMatrix().mapRect(invalidateRectf);
+ invalidateRectf.offset(-xoffset, -yoffset);
+
+ invalidateRect.set((int) Math.floor(invalidateRectf.left),
+ (int) Math.floor(invalidateRectf.top),
+ (int) Math.ceil(invalidateRectf.right),
+ (int) Math.ceil(invalidateRectf.bottom));
+
+ invalidateGlobalRegion(mView, invalidateRect);
+ }
+ }
+ }
+
+ private static class HolographicHelper {
+ private final Paint mHolographicPaint = new Paint();
+ private final Paint mErasePaint = new Paint();
+ private final float STROKE_WIDTH = 3.0f;
+
+ HolographicHelper() {
+ initializePaints();
+ }
+
+ void initializePaints() {
+ mHolographicPaint.setColor(0xff6699ff);
+ mHolographicPaint.setFilterBitmap(true);
+ mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+ mErasePaint.setFilterBitmap(true);
+ }
+
+ Bitmap createOutline(View v) {
+ if (v.getMeasuredWidth() == 0 || v.getMeasuredHeight() == 0) {
+ return null;
+ }
+
+ Bitmap bitmap = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(),
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+
+ float rotationX = v.getRotationX();
+ v.setRotationX(0);
+ canvas.concat(v.getMatrix());
+ v.draw(canvas);
+
+ v.setRotationX(rotationX);
+
+ drawOutline(canvas, bitmap);
+ return bitmap;
+ }
+
+ final Matrix id = new Matrix();
+ final Matrix scaleMatrix = new Matrix();
+ void drawOutline(Canvas dest, Bitmap src) {
+ Bitmap mask = src.extractAlpha();
+
+ dest.drawColor(0, PorterDuff.Mode.CLEAR);
+
+ float xScale = STROKE_WIDTH*2/(dest.getWidth());
+ float yScale = STROKE_WIDTH*2/(dest.getHeight());
+
+ scaleMatrix.reset();
+ scaleMatrix.preScale(1+xScale, 1+yScale, dest.getWidth()/2, dest.getHeight()/2);
+ dest.setMatrix(id);
+ dest.drawBitmap(mask, scaleMatrix, mHolographicPaint);
+ dest.drawBitmap(mask, id, mErasePaint);
+ mask.recycle();
+ }
}
}
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index ef0ab41..1048352 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -110,13 +110,13 @@
com.android.internal.R.id.lower_action_context_bar);
mAnimatorView = (ViewAnimator) decor.findViewById(
com.android.internal.R.id.action_bar_animator);
- mActionView.setContextView(mUpperContextView);
-
+
if (mActionView == null || mUpperContextView == null || mAnimatorView == null) {
throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
"with a compatible window decor layout");
}
+ mActionView.setContextView(mUpperContextView);
mContextDisplayMode = mLowerContextView == null ?
CONTEXT_DISPLAY_NORMAL : CONTEXT_DISPLAY_SPLIT;
}
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index dba1cea..6f6d919 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -506,7 +506,7 @@
static void readLocale(char* language, char* region)
{
char propLang[PROPERTY_VALUE_MAX], propRegn[PROPERTY_VALUE_MAX];
-
+
property_get("persist.sys.language", propLang, "");
property_get("persist.sys.country", propRegn, "");
if (*propLang == 0 && *propRegn == 0) {
@@ -701,6 +701,42 @@
}
}
+ /* enable poisoning of memory of freed objects */
+ property_get("dalvik.vm.gc.overwritefree", propBuf, "false");
+ if (strcmp(propBuf, "true") == 0) {
+ opt.optionString = "-Xgc:overwritefree";
+ mOptions.add(opt);
+ } else if (strcmp(propBuf, "false") != 0) {
+ LOGW("dalvik.vm.gc.overwritefree should be 'true' or 'false'");
+ }
+
+ /* enable heap verification before each gc */
+ property_get("dalvik.vm.gc.preverify", propBuf, "false");
+ if (strcmp(propBuf, "true") == 0) {
+ opt.optionString = "-Xgc:preverify";
+ mOptions.add(opt);
+ } else if (strcmp(propBuf, "false") != 0) {
+ LOGW("dalvik.vm.gc.preverify should be 'true' or 'false'");
+ }
+
+ /* enable heap verification after each gc */
+ property_get("dalvik.vm.gc.postverify", propBuf, "false");
+ if (strcmp(propBuf, "true") == 0) {
+ opt.optionString = "-Xgc:postverify";
+ mOptions.add(opt);
+ } else if (strcmp(propBuf, "false") != 0) {
+ LOGW("dalvik.vm.gc.postverify should be 'true' or 'false'");
+ }
+
+ /* enable card table verification for partial gc */
+ property_get("dalvik.vm.gc.verifycardtable", propBuf, "false");
+ if (strcmp(propBuf, "true") == 0) {
+ opt.optionString = "-Xgc:verifycardtable";
+ mOptions.add(opt);
+ } else if (strcmp(propBuf, "false") != 0) {
+ LOGW("dalvik.vm.gc.verifycardtable should be 'true' or 'false'");
+ }
+
/* enable debugging; set suspend=y to pause during VM init */
#ifdef HAVE_ANDROID_OS
/* use android ADB transport */
@@ -748,16 +784,6 @@
}
#if defined(WITH_JIT)
- /* Minimal profile threshold to trigger JIT compilation */
- char jitThresholdBuf[sizeof("-Xjitthreshold:") + PROPERTY_VALUE_MAX];
- property_get("dalvik.vm.jit.threshold", propBuf, "");
- if (strlen(propBuf) > 0) {
- strcpy(jitThresholdBuf, "-Xjitthreshold:");
- strcat(jitThresholdBuf, propBuf);
- opt.optionString = jitThresholdBuf;
- mOptions.add(opt);
- }
-
/* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.jit.op", propBuf, "");
@@ -768,16 +794,6 @@
mOptions.add(opt);
}
- /*
- * Reverse the polarity of dalvik.vm.jit.op and force interpreter-only
- * for non-selected opcodes.
- */
- property_get("dalvik.vm.jit.includeop", propBuf, "");
- if (strlen(propBuf) > 0) {
- opt.optionString = "-Xincludeselectedop";
- mOptions.add(opt);
- }
-
/* Force interpreter-only mode for selected methods */
char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX];
property_get("dalvik.vm.jit.method", propBuf, "");
@@ -787,37 +803,6 @@
opt.optionString = jitMethodBuf;
mOptions.add(opt);
}
-
- /*
- * Reverse the polarity of dalvik.vm.jit.method and force interpreter-only
- * for non-selected methods.
- */
- property_get("dalvik.vm.jit.includemethod", propBuf, "");
- if (strlen(propBuf) > 0) {
- opt.optionString = "-Xincludeselectedmethod";
- mOptions.add(opt);
- }
-
- /*
- * Enable profile collection on JIT'ed code.
- */
- property_get("dalvik.vm.jit.profile", propBuf, "");
- if (strlen(propBuf) > 0) {
- opt.optionString = "-Xjitprofile";
- mOptions.add(opt);
- }
-
- /*
- * Disable optimizations by setting the corresponding bit to 1.
- */
- char jitOptBuf[sizeof("-Xjitdisableopt:") + PROPERTY_VALUE_MAX];
- property_get("dalvik.vm.jit.disableopt", propBuf, "");
- if (strlen(propBuf) > 0) {
- strcpy(jitOptBuf, "-Xjitdisableopt:");
- strcat(jitOptBuf, propBuf);
- opt.optionString = jitOptBuf;
- mOptions.add(opt);
- }
#endif
if (executionMode == kEMIntPortable) {
diff --git a/core/res/res/raw-rm/loaderror.html b/core/res/res/raw-rm/loaderror.html
new file mode 100644
index 0000000..8e4a3fe
--- /dev/null
+++ b/core/res/res/raw-rm/loaderror.html
@@ -0,0 +1,18 @@
+<html>
+ <head>
+ <title>Pagina d'internet betg disponibla</title>
+ <style type="text/css">
+ body { margin-top: 0px; padding-top: 0px; }
+ h2 { margin-top: 5px; padding-top: 0px; }
+ </style>
+
+ <body>
+
+ <img src="file:///android_asset/webkit/android-weberror.png" align="top" />
+ <h2>Pagina d'internet betg disponibla</h2>
+ <p>Impussibel da chargiar la pagina d'internet sut <a href="%s">%s</a>. Errur:</p>
+ <!-- The %e is replaced by a localized error string -->
+ <p>%e</p>
+ </body>
+ </head>
+</html>
diff --git a/core/res/res/raw-rm/nodomain.html b/core/res/res/raw-rm/nodomain.html
new file mode 100644
index 0000000..1e2833b
--- /dev/null
+++ b/core/res/res/raw-rm/nodomain.html
@@ -0,0 +1,23 @@
+<html>
+ <head>
+ <title>Pagina d'internet betg disponibla</title>
+ <style type="text/css">
+ body { margin-top: 0px; padding-top: 0px; }
+ h2 { margin-top: 5px; padding-top: 0px; }
+ </style>
+
+ <body>
+
+ <img src="file:///android_asset/webkit/android-weberror.png" align="top" />
+ <h2>Pagina d'internet betg disponibla</h2>
+ <p>La pagina d'internet sut <a href="%s">%s</a> è eventualmain deactivada temporarmain u spustada definitivamain ad ina nova adressa da web.</p>
+
+ <p><b>Qua in pèr propostas:</b></p>
+ <ul>
+ <li>Controllai che Voss apparat recepescha in signal e dispona d'ina connexiun da datas.</li>
+ <li>Chargiai pli tard danovamain la pagina d'internet.</li>
+ <li>Chargiai ina copia da la pagina da web memorisada en il cache da Google.</li>
+ </ul>
+ </body>
+ </head>
+</html>
diff --git a/core/res/res/values-rm/donottranslate-cldr.xml b/core/res/res/values-rm/donottranslate-cldr.xml
new file mode 100644
index 0000000..4b9f9db
--- /dev/null
+++ b/core/res/res/values-rm/donottranslate-cldr.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">schaner</string>
+ <string name="month_long_standalone_february">favrer</string>
+ <string name="month_long_standalone_march">mars</string>
+ <string name="month_long_standalone_april">avrigl</string>
+ <string name="month_long_standalone_may">matg</string>
+ <string name="month_long_standalone_june">zercladur</string>
+ <string name="month_long_standalone_july">fanadur</string>
+ <string name="month_long_standalone_august">avust</string>
+ <string name="month_long_standalone_september">settember</string>
+ <string name="month_long_standalone_october">october</string>
+ <string name="month_long_standalone_november">november</string>
+ <string name="month_long_standalone_december">december</string>
+
+ <string name="month_long_january">schaner</string>
+ <string name="month_long_february">favrer</string>
+ <string name="month_long_march">mars</string>
+ <string name="month_long_april">avrigl</string>
+ <string name="month_long_may">matg</string>
+ <string name="month_long_june">zercladur</string>
+ <string name="month_long_july">fanadur</string>
+ <string name="month_long_august">avust</string>
+ <string name="month_long_september">settember</string>
+ <string name="month_long_october">october</string>
+ <string name="month_long_november">november</string>
+ <string name="month_long_december">december</string>
+
+ <string name="month_medium_january">schan.</string>
+ <string name="month_medium_february">favr.</string>
+ <string name="month_medium_march">mars</string>
+ <string name="month_medium_april">avr.</string>
+ <string name="month_medium_may">matg</string>
+ <string name="month_medium_june">zercl.</string>
+ <string name="month_medium_july">fan.</string>
+ <string name="month_medium_august">avust</string>
+ <string name="month_medium_september">sett.</string>
+ <string name="month_medium_october">oct.</string>
+ <string name="month_medium_november">nov.</string>
+ <string name="month_medium_december">dec.</string>
+
+ <string name="month_shortest_january">S</string>
+ <string name="month_shortest_february">F</string>
+ <string name="month_shortest_march">M</string>
+ <string name="month_shortest_april">A</string>
+ <string name="month_shortest_may">M</string>
+ <string name="month_shortest_june">Z</string>
+ <string name="month_shortest_july">F</string>
+ <string name="month_shortest_august">A</string>
+ <string name="month_shortest_september">S</string>
+ <string name="month_shortest_october">O</string>
+ <string name="month_shortest_november">N</string>
+ <string name="month_shortest_december">D</string>
+
+ <string name="sunday">dumengia</string>
+ <string name="monday">glindesdi</string>
+ <string name="tuesday">mardi</string>
+ <string name="wednesday">mesemna</string>
+ <string name="thursday">gievgia</string>
+ <string name="friday">venderdi</string>
+ <string name="saturday">sonda</string>
+
+ <string name="day_of_week_long_sunday">dumengia</string>
+ <string name="day_of_week_long_monday">glindesdi</string>
+ <string name="day_of_week_long_tuesday">mardi</string>
+ <string name="day_of_week_long_wednesday">mesemna</string>
+ <string name="day_of_week_long_thursday">gievgia</string>
+ <string name="day_of_week_long_friday">venderdi</string>
+ <string name="day_of_week_long_saturday">sonda</string>
+
+ <string name="day_of_week_medium_sunday">du</string>
+ <string name="day_of_week_medium_monday">gli</string>
+ <string name="day_of_week_medium_tuesday">ma</string>
+ <string name="day_of_week_medium_wednesday">me</string>
+ <string name="day_of_week_medium_thursday">gie</string>
+ <string name="day_of_week_medium_friday">ve</string>
+ <string name="day_of_week_medium_saturday">so</string>
+
+ <string name="day_of_week_short_sunday">du</string>
+ <string name="day_of_week_short_monday">gli</string>
+ <string name="day_of_week_short_tuesday">ma</string>
+ <string name="day_of_week_short_wednesday">me</string>
+ <string name="day_of_week_short_thursday">gie</string>
+ <string name="day_of_week_short_friday">ve</string>
+ <string name="day_of_week_short_saturday">so</string>
+
+ <string name="day_of_week_shorter_sunday">D</string>
+ <string name="day_of_week_shorter_monday">G</string>
+ <string name="day_of_week_shorter_tuesday">M</string>
+ <string name="day_of_week_shorter_wednesday">M</string>
+ <string name="day_of_week_shorter_thursday">G</string>
+ <string name="day_of_week_shorter_friday">V</string>
+ <string name="day_of_week_shorter_saturday">S</string>
+
+ <string name="day_of_week_shortest_sunday">D</string>
+ <string name="day_of_week_shortest_monday">G</string>
+ <string name="day_of_week_shortest_tuesday">M</string>
+ <string name="day_of_week_shortest_wednesday">M</string>
+ <string name="day_of_week_shortest_thursday">G</string>
+ <string name="day_of_week_shortest_friday">V</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="yesterday">ier</string>
+ <string name="today">oz</string>
+ <string name="tomorrow">damaun</string>
+
+ <string name="hour_minute_24">%-k:%M</string>
+ <string name="hour_minute_ampm">%-l:%M %p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+ <string name="twelve_hour_time_format">h:mm a</string>
+ <string name="twenty_four_hour_time_format">H:mm</string>
+ <string name="numeric_date">%d.%m.%Y</string>
+ <string name="numeric_date_format">dd.MM.yyyy</string>
+ <string name="numeric_date_template">"%s.%s.%s"</string>
+ <string name="month_day_year">%-e. %B %Y</string>
+ <string name="full_date_month_first">d. MMMM y</string>
+ <string name="full_date_day_first">d. MMMM y</string>
+ <string name="medium_date_month_first">d. MMM y</string>
+ <string name="medium_date_day_first">d. MMM y</string>
+ <string name="time_of_day">%H:%M:%S</string>
+ <string name="status_bar_time_format">HH:mm</string>
+ <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
+ <string name="date_time">%1$s, %2$s</string>
+ <string name="time_date">%3$s, %1$s</string>
+ <string name="abbrev_month_day_year">%d.%m.%Y</string>
+ <string name="month_day">%-e. %B</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%-e. %b</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+ <string name="time1_time2">%1$s - %2$s</string>
+ <string name="date1_date2">%2$s - %5$s</string>
+ <string name="numeric_md1_md2">%3$s.%2$s. - %8$s.%7$s.</string>
+ <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
+ <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
+ <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+ <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
+ <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
+ <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
+ <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
+ <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
+ <string name="time_wday_date">%1$s %2$s %3$s</string>
+ <string name="wday_date">%2$s %3$s</string>
+ <string name="time_wday">%1$s %2$s</string>
+ <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
+ <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
+ <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
+ <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
+ <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string>
+ <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
+ <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
+ <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
+ <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
+ <string name="short_format_month">%b</string>
+</resources>
diff --git a/docs/html/guide/topics/fundamentals.jd b/docs/html/guide/topics/fundamentals.jd
index 6d6abd8..db06efc 100644
--- a/docs/html/guide/topics/fundamentals.jd
+++ b/docs/html/guide/topics/fundamentals.jd
@@ -292,8 +292,8 @@
<li><p>A service is started (or new instructions are given to an ongoing
service) by passing an Intent object to <code>{@link
android.content.Context#startService Context.startService()}</code>.
-Android calls the service's <code>{@link android.app.Service#onStart
-onStart()}</code> method and passes it the Intent object.</p>
+Android calls the service's <code>{@link android.app.Service#onStartCommand
+onStartCommand()}</code> method and passes it the Intent object.</p>
<p>
Similarly, an intent can be passed to <code>{@link
@@ -1508,9 +1508,9 @@
in {@code onCreate()}, and then stop the thread in {@code onDestroy()}.</li>
<li><p>The <b>active lifetime</b> of a service begins with a call to
-<code>{@link android.app.Service#onStart onStart()}</code>. This method
+<code>{@link android.app.Service#onStartCommand onStartCommand()}</code>. This method
is handed the Intent object that was passed to {@code startService()}.
-The music service would open the Intent to discover which music to
+The music service would open the Intent to discover which music to
play, and begin the playback.</p>
<p>
@@ -1525,7 +1525,7 @@
<code>{@link android.content.Context#startService Context.startService()}</code>
or
<code>{@link android.content.Context#bindService Context.bindService()}</code>.
-However, {@code onStart()} is called only for services started by {@code
+However, {@code onStartCommand()} is called only for services started by {@code
startService()}.
</p>
@@ -1629,7 +1629,7 @@
<li><p>It has a {@link android.app.Service} object that's executing
one of its lifecycle callbacks (<code>{@link android.app.Service#onCreate
-onCreate()}</code>, <code>{@link android.app.Service#onStart onStart()}</code>,
+onCreate()}</code>, <code>{@link android.app.Service#onStartCommand onStartCommand()}</code>,
or <code>{@link android.app.Service#onDestroy onDestroy()}</code>).</p></li>
<li><p>It has a {@link android.content.BroadcastReceiver} object that's
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index b811479..ed09f89 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -54,16 +54,20 @@
UNSIGNED_5_5_5_1 (14, 2),
UNSIGNED_4_4_4_4 (15, 2),
- RS_ELEMENT (16, 4),
- RS_TYPE (17, 4),
- RS_ALLOCATION (18, 4),
- RS_SAMPLER (19, 4),
- RS_SCRIPT (20, 4),
- RS_MESH (21, 4),
- RS_PROGRAM_FRAGMENT (22, 4),
- RS_PROGRAM_VERTEX (23, 4),
- RS_PROGRAM_RASTER (24, 4),
- RS_PROGRAM_STORE (25, 4);
+ MATRIX_4X4 (16, 64),
+ MATRIX_3X3 (17, 36),
+ MATRIX_2X2 (18, 16),
+
+ RS_ELEMENT (1000, 4),
+ RS_TYPE (1001, 4),
+ RS_ALLOCATION (1002, 4),
+ RS_SAMPLER (1003, 4),
+ RS_SCRIPT (1004, 4),
+ RS_MESH (1005, 4),
+ RS_PROGRAM_FRAGMENT (1006, 4),
+ RS_PROGRAM_VERTEX (1007, 4),
+ RS_PROGRAM_RASTER (1008, 4),
+ RS_PROGRAM_STORE (1009, 4);
int mID;
int mSize;
@@ -285,6 +289,29 @@
return rs.mElement_UCHAR_4;
}
+ public static Element MATRIX_4X4(RenderScript rs) {
+ if(rs.mElement_MATRIX_4X4 == null) {
+ rs.mElement_MATRIX_4X4 = createUser(rs, DataType.MATRIX_4X4);
+ }
+ return rs.mElement_MATRIX_4X4;
+ }
+ public static Element MATRIX4X4(RenderScript rs) {
+ return MATRIX_4X4(rs);
+ }
+
+ public static Element MATRIX_3X3(RenderScript rs) {
+ if(rs.mElement_MATRIX_3X3 == null) {
+ rs.mElement_MATRIX_3X3 = createUser(rs, DataType.MATRIX_3X3);
+ }
+ return rs.mElement_MATRIX_4X4;
+ }
+
+ public static Element MATRIX_2X2(RenderScript rs) {
+ if(rs.mElement_MATRIX_2X2 == null) {
+ rs.mElement_MATRIX_2X2 = createUser(rs, DataType.MATRIX_2X2);
+ }
+ return rs.mElement_MATRIX_2X2;
+ }
Element(int id, RenderScript rs, Element[] e, String[] n) {
super(id, rs);
diff --git a/graphics/java/android/renderscript/FieldPacker.java b/graphics/java/android/renderscript/FieldPacker.java
index 24f0409..b6f88be 100644
--- a/graphics/java/android/renderscript/FieldPacker.java
+++ b/graphics/java/android/renderscript/FieldPacker.java
@@ -248,6 +248,24 @@
addU32(v.w);
}
+ public void addObj(Matrix4f v) {
+ for (int i=0; i < v.mMat.length; i++) {
+ addF32(v.mMat[i]);
+ }
+ }
+
+ public void addObj(Matrix3f v) {
+ for (int i=0; i < v.mMat.length; i++) {
+ addF32(v.mMat[i]);
+ }
+ }
+
+ public void addObj(Matrix2f v) {
+ for (int i=0; i < v.mMat.length; i++) {
+ addF32(v.mMat[i]);
+ }
+ }
+
public void addBoolean(boolean v) {
addI8((byte)(v ? 1 : 0));
}
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index ab1d7650..08ba7e2 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -542,6 +542,10 @@
Element mElement_FLOAT_4;
Element mElement_UCHAR_4;
+ Element mElement_MATRIX_4X4;
+ Element mElement_MATRIX_3X3;
+ Element mElement_MATRIX_2X2;
+
Sampler mSampler_CLAMP_NEAREST;
Sampler mSampler_CLAMP_LINEAR;
Sampler mSampler_CLAMP_LINEAR_MIP_LINEAR;
@@ -614,15 +618,22 @@
int[] rbuf = new int[16];
mRS.nContextInitToClient(mRS.mContext);
while(mRun) {
+ rbuf[0] = 0;
int msg = mRS.nContextGetMessage(mRS.mContext, rbuf, true);
if (msg == 0) {
- // Should only happen during teardown.
- // But we want to avoid starving other threads during
- // teardown by yielding until the next line in the destructor
- // can execute to set mRun = false
- try {
- sleep(1, 0);
- } catch(InterruptedException e) {
+ // Can happen for two reasons
+ if (rbuf[0] > 0) {
+ // 1: Buffer needs to be enlarged.
+ rbuf = new int[rbuf[0] + 2];
+ } else {
+ // 2: teardown.
+ // But we want to avoid starving other threads during
+ // teardown by yielding until the next line in the destructor
+ // can execute to set mRun = false
+ try {
+ sleep(1, 0);
+ } catch(InterruptedException e) {
+ }
}
}
if(mRS.mMessageCallback != null) {
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index b2e8dd9..81f08e9 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -228,7 +228,8 @@
size_t receiveLen;
int id = rsContextGetMessage(con, ptr, &receiveLen, len * 4, wait);
if (!id && receiveLen) {
- LOGE("message receive buffer too small. %i", receiveLen);
+ LOGV("message receive buffer too small. %i", receiveLen);
+ *ptr = (jint)receiveLen;
}
_env->ReleaseIntArrayElements(data, ptr, 0);
return id;
diff --git a/include/media/EffectPresetReverbApi.h b/include/media/EffectPresetReverbApi.h
index 53205bb..a3f094c 100644
--- a/include/media/EffectPresetReverbApi.h
+++ b/include/media/EffectPresetReverbApi.h
@@ -43,7 +43,8 @@
REVERB_PRESET_LARGEROOM,
REVERB_PRESET_MEDIUMHALL,
REVERB_PRESET_LARGEHALL,
- REVERB_PRESET_PLATE
+ REVERB_PRESET_PLATE,
+ REVERB_PRESET_LAST = REVERB_PRESET_PLATE
} t_reverb_presets;
#if __cplusplus
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index 6f7dc38..9d2cff6 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -28,6 +28,7 @@
namespace android {
+struct AMessage;
class String8;
class DataSource : public RefBase {
@@ -59,10 +60,14 @@
////////////////////////////////////////////////////////////////////////////
- bool sniff(String8 *mimeType, float *confidence);
+ bool sniff(String8 *mimeType, float *confidence, sp<AMessage> *meta);
+ // The sniffer can optionally fill in "meta" with an AMessage containing
+ // a dictionary of values that helps the corresponding extractor initialize
+ // its state without duplicating effort already exerted by the sniffer.
typedef bool (*SnifferFunc)(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType,
+ float *confidence, sp<AMessage> *meta);
static void RegisterSniffer(SnifferFunc func);
static void RegisterDefaultSniffers();
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 3406287..7902b9a 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -91,7 +91,11 @@
RS_TYPE_UNSIGNED_5_5_5_1,
RS_TYPE_UNSIGNED_4_4_4_4,
- RS_TYPE_ELEMENT,
+ RS_TYPE_MATRIX_4X4,
+ RS_TYPE_MATRIX_3X3,
+ RS_TYPE_MATRIX_2X2,
+
+ RS_TYPE_ELEMENT = 1000,
RS_TYPE_TYPE,
RS_TYPE_ALLOCATION,
RS_TYPE_SAMPLER,
@@ -100,7 +104,7 @@
RS_TYPE_PROGRAM_FRAGMENT,
RS_TYPE_PROGRAM_VERTEX,
RS_TYPE_PROGRAM_RASTER,
- RS_TYPE_PROGRAM_STORE
+ RS_TYPE_PROGRAM_STORE,
};
enum RsDataKind {
diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SgTransform.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SgTransform.java
index bfc9bb7..e70e811 100644
--- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SgTransform.java
+++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SgTransform.java
@@ -82,15 +82,8 @@
void setData() {
- mTransformData.globalMat_Row0 = new Float4(1, 0, 0, 0);
- mTransformData.globalMat_Row1 = new Float4(0, 1, 0, 0);
- mTransformData.globalMat_Row2 = new Float4(0, 0, 1, 0);
- mTransformData.globalMat_Row3 = new Float4(0, 0, 0, 1);
-
- mTransformData.localMat_Row0 = new Float4(1, 0, 0, 0);
- mTransformData.localMat_Row1 = new Float4(0, 1, 0, 0);
- mTransformData.localMat_Row2 = new Float4(0, 0, 1, 0);
- mTransformData.localMat_Row3 = new Float4(0, 0, 0, 1);
+ mTransformData.globalMat = new Matrix4f();
+ mTransformData.localMat = new Matrix4f();
mTransformData.transforms0 = mTransforms[0];
mTransformData.transforms1 = mTransforms[1];
diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/scenegraph.rs b/libs/rs/java/ModelViewer/src/com/android/modelviewer/scenegraph.rs
index 8053306..c794438 100644
--- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/scenegraph.rs
+++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/scenegraph.rs
@@ -76,10 +76,10 @@
rsgBindProgramStore(gPFSBackground);
rsgBindTexture(gPFBackground, 0, gTGrid);
- rsgProgramVertexLoadModelMatrix((rs_matrix4x4 *)&robot1Ptr->globalMat_Row0);
+ rsgProgramVertexLoadModelMatrix(&robot1Ptr->globalMat);
rsgDrawMesh(gTestMesh);
- rsgProgramVertexLoadModelMatrix((rs_matrix4x4 *)&robot2Ptr->globalMat_Row0);
+ rsgProgramVertexLoadModelMatrix(&robot2Ptr->globalMat);
rsgDrawMesh(gTestMesh);
color(0.3f, 0.3f, 0.3f, 1.0f);
diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform.rs b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform.rs
index 7b9cd1c..2ef29cf 100644
--- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform.rs
+++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform.rs
@@ -52,8 +52,8 @@
//rsDebug("Transform data", (int)data);
//rsDebug("Entering parent", (int)parent);
- rs_matrix4x4 *localMat = (rs_matrix4x4*)&data->localMat_Row0;
- rs_matrix4x4 *globalMat = (rs_matrix4x4*)&data->globalMat_Row0;
+ rs_matrix4x4 *localMat = &data->localMat;
+ rs_matrix4x4 *globalMat = &data->globalMat;
ParentData toChild;
toChild.changed = 0;
diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh
index a66e6c5..5c872a7 100644
--- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh
+++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh
@@ -22,15 +22,8 @@
#define TRANSFORM_SCALE 3
typedef struct {
- float4 globalMat_Row0;
- float4 globalMat_Row1;
- float4 globalMat_Row2;
- float4 globalMat_Row3;
-
- float4 localMat_Row0;
- float4 localMat_Row1;
- float4 localMat_Row2;
- float4 localMat_Row3;
+ rs_matrix4x4 globalMat;
+ rs_matrix4x4 localMat;
float4 transforms0;
float4 transforms1;
diff --git a/libs/rs/rsComponent.cpp b/libs/rs/rsComponent.cpp
index fbaa75f..f51b23e 100644
--- a/libs/rs/rsComponent.cpp
+++ b/libs/rs/rsComponent.cpp
@@ -95,6 +95,26 @@
mNormalized = true;
rsAssert(mKind == RS_KIND_PIXEL_RGBA);
return;
+
+ case RS_TYPE_MATRIX_4X4:
+ mTypeBits = 16 * 32;
+ rsAssert(mVectorSize == 1);
+ rsAssert(mNormalized == false);
+ rsAssert(mKind == RS_KIND_USER);
+ break;
+ case RS_TYPE_MATRIX_3X3:
+ mTypeBits = 9 * 32;
+ rsAssert(mVectorSize == 1);
+ rsAssert(mNormalized == false);
+ rsAssert(mKind == RS_KIND_USER);
+ break;
+ case RS_TYPE_MATRIX_2X2:
+ mTypeBits = 4 * 32;
+ rsAssert(mVectorSize == 1);
+ rsAssert(mNormalized == false);
+ rsAssert(mKind == RS_KIND_USER);
+ break;
+
case RS_TYPE_ELEMENT:
case RS_TYPE_TYPE:
case RS_TYPE_ALLOCATION:
@@ -218,10 +238,19 @@
case 4: return String8("vec4");
}
}
+ if ((mType == RS_TYPE_MATRIX_4X4) && (mVectorSize == 1)) {
+ return String8("mat4");
+ }
+ if ((mType == RS_TYPE_MATRIX_3X3) && (mVectorSize == 1)) {
+ return String8("mat3");
+ }
+ if ((mType == RS_TYPE_MATRIX_2X2) && (mVectorSize == 1)) {
+ return String8("mat2");
+ }
return String8();
}
-static const char * gTypeStrings[] = {
+static const char * gTypeBasicStrings[] = {
"NONE",
"F16",
"F32",
@@ -238,6 +267,12 @@
"UP_565",
"UP_5551",
"UP_4444",
+ "MATRIX_4X4",
+ "MATRIX_3X3",
+ "MATRIX_2X2",
+};
+
+static const char * gTypeObjStrings[] = {
"ELEMENT",
"TYPE",
"ALLOCATION",
@@ -267,8 +302,13 @@
void Component::dumpLOGV(const char *prefix) const
{
- LOGV("%s Component: %s, %s, vectorSize=%i, bits=%i",
- prefix, gTypeStrings[mType], gKindStrings[mKind], mVectorSize, mBits);
+ if (mType >= RS_TYPE_ELEMENT) {
+ LOGV("%s Component: %s, %s, vectorSize=%i, bits=%i",
+ prefix, gTypeObjStrings[mType - RS_TYPE_ELEMENT], gKindStrings[mKind], mVectorSize, mBits);
+ } else {
+ LOGV("%s Component: %s, %s, vectorSize=%i, bits=%i",
+ prefix, gTypeBasicStrings[mType], gKindStrings[mKind], mVectorSize, mBits);
+ }
}
void Component::serialize(OStream *stream) const
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 08dd57b..f67a9d5 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -713,10 +713,10 @@
uint32_t Context::getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait)
{
//LOGE("getMessageToClient %i %i", bufferLen, wait);
+ *receiveLen = 0;
if (!wait) {
if (mIO.mToClient.isEmpty()) {
// No message to get and not going to wait for one.
- receiveLen = 0;
return 0;
}
}
diff --git a/media/java/android/media/MtpDatabase.java b/media/java/android/media/MtpDatabase.java
index 88cce46..7e0d390 100644
--- a/media/java/android/media/MtpDatabase.java
+++ b/media/java/android/media/MtpDatabase.java
@@ -66,14 +66,6 @@
private final MediaScanner mMediaScanner;
- // MTP property codes
- private static final int MTP_PROPERTY_STORAGE_ID = 0xDC01;
- private static final int MTP_PROPERTY_OBJECT_FORMAT = 0xDC02;
- private static final int MTP_PROPERTY_OBJECT_SIZE = 0xDC04;
- private static final int MTP_PROPERTY_OBJECT_FILE_NAME = 0xDC07;
- private static final int MTP_PROPERTY_DATE_MODIFIED = 0xDC09;
- private static final int MTP_PROPERTY_PARENT_OBJECT = 0xDC0B;
-
// MTP response codes
private static final int MTP_RESPONSE_OK = 0x2001;
private static final int MTP_RESPONSE_GENERAL_ERROR = 0x2002;
@@ -271,25 +263,36 @@
boolean isString = false;
switch (property) {
- case MTP_PROPERTY_STORAGE_ID:
+ case Mtp.Object.PROPERTY_STORAGE_ID:
outIntValue[0] = mStorageID;
return MTP_RESPONSE_OK;
- case MTP_PROPERTY_OBJECT_FORMAT:
+ case Mtp.Object.PROPERTY_OBJECT_FORMAT:
column = MtpObjects.ObjectColumns.FORMAT;
break;
- case MTP_PROPERTY_OBJECT_SIZE:
+ case Mtp.Object.PROPERTY_PROTECTION_STATUS:
+ // protection status is always 0
+ outIntValue[0] = 0;
+ return MTP_RESPONSE_OK;
+ case Mtp.Object.PROPERTY_OBJECT_SIZE:
column = MtpObjects.ObjectColumns.SIZE;
break;
- case MTP_PROPERTY_OBJECT_FILE_NAME:
+ case Mtp.Object.PROPERTY_OBJECT_FILE_NAME:
column = MtpObjects.ObjectColumns.DATA;
isString = true;
break;
- case MTP_PROPERTY_DATE_MODIFIED:
+ case Mtp.Object.PROPERTY_DATE_MODIFIED:
column = MtpObjects.ObjectColumns.DATE_MODIFIED;
break;
- case MTP_PROPERTY_PARENT_OBJECT:
+ case Mtp.Object.PROPERTY_PARENT_OBJECT:
column = MtpObjects.ObjectColumns.PARENT;
break;
+ case Mtp.Object.PROPERTY_PERSISTENT_UID:
+ // PUID is concatenation of storageID and object handle
+ long puid = mStorageID;
+ puid <<= 32;
+ puid += handle;
+ outIntValue[0] = puid;
+ return MTP_RESPONSE_OK;
default:
return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
}
@@ -305,7 +308,7 @@
String value = c.getString(1);
int start = 0;
- if (property == MTP_PROPERTY_OBJECT_FILE_NAME) {
+ if (property == Mtp.Object.PROPERTY_OBJECT_FILE_NAME) {
// extract name from full path
int lastSlash = value.lastIndexOf('/');
if (lastSlash >= 0) {
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index bf83172..4ef3a9f 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -29,6 +29,7 @@
#include "MtpDatabase.h"
#include "MtpDataPacket.h"
+#include "MtpProperty.h"
#include "MtpUtils.h"
#include "mtp.h"
@@ -45,6 +46,7 @@
static jmethodID method_getSupportedObjectProperties;
static jmethodID method_getSupportedDeviceProperties;
static jmethodID method_getObjectProperty;
+static jmethodID method_setObjectProperty;
static jmethodID method_getObjectInfo;
static jmethodID method_getObjectFilePath;
static jmethodID method_deleteFile;
@@ -98,10 +100,22 @@
virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format);
virtual MtpDevicePropertyList* getSupportedDeviceProperties();
- virtual MtpResponseCode getObjectProperty(MtpObjectHandle handle,
+ virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle,
MtpObjectProperty property,
MtpDataPacket& packet);
+ virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle,
+ MtpObjectProperty property,
+ MtpDataPacket& packet);
+
+ virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property,
+ MtpDataPacket& packet);
+
+ virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property,
+ MtpDataPacket& packet);
+
+ virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property);
+
virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
MtpDataPacket& packet);
@@ -116,6 +130,11 @@
virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
MtpObjectHandleList* references);
+
+ virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
+ MtpObjectFormat format);
+
+ virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property);
};
// ----------------------------------------------------------------------------
@@ -292,7 +311,7 @@
return list;
}
-MtpResponseCode MyMtpDatabase::getObjectProperty(MtpObjectHandle handle,
+MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
MtpObjectProperty property,
MtpDataPacket& packet) {
int type;
@@ -310,6 +329,15 @@
jlong longValue = longValues[0];
env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
+ // special case MTP_PROPERTY_DATE_MODIFIED, which is a string to MTP
+ // but stored internally as a uint64
+ if (property == MTP_PROPERTY_DATE_MODIFIED) {
+ char date[20];
+ formatDateTime(longValue, date, sizeof(date));
+ packet.putString(date);
+ return MTP_RESPONSE_OK;
+ }
+
switch (type) {
case MTP_TYPE_INT8:
packet.putInt8(longValue);
@@ -335,6 +363,12 @@
case MTP_TYPE_UINT64:
packet.putUInt64(longValue);
break;
+ case MTP_TYPE_INT128:
+ packet.putInt128(longValue);
+ break;
+ case MTP_TYPE_UINT128:
+ packet.putInt128(longValue);
+ break;
case MTP_TYPE_STR:
{
jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
@@ -351,6 +385,26 @@
return MTP_RESPONSE_OK;
}
+MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
+ MtpObjectProperty property,
+ MtpDataPacket& packet) {
+ return -1;
+}
+
+MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
+ MtpDataPacket& packet) {
+ return -1;
+}
+
+MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
+ MtpDataPacket& packet) {
+ return -1;
+}
+
+MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
+ return -1;
+}
+
MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
MtpDataPacket& packet) {
char date[20];
@@ -372,9 +426,10 @@
uint64_t modified = longValues[1];
env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
- int associationType = (format == MTP_FORMAT_ASSOCIATION ?
- MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
- MTP_ASSOCIATION_TYPE_UNDEFINED);
+// int associationType = (format == MTP_FORMAT_ASSOCIATION ?
+// MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
+// MTP_ASSOCIATION_TYPE_UNDEFINED);
+ int associationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
packet.putUInt32(storageID);
packet.putUInt16(format);
@@ -497,6 +552,37 @@
return result;
}
+MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
+ MtpObjectFormat format) {
+ MtpProperty* result = NULL;
+ switch (property) {
+ case MTP_PROPERTY_OBJECT_FORMAT:
+ case MTP_PROPERTY_PROTECTION_STATUS:
+ result = new MtpProperty(property, MTP_TYPE_UINT16);
+ break;
+ case MTP_PROPERTY_STORAGE_ID:
+ case MTP_PROPERTY_PARENT_OBJECT:
+ result = new MtpProperty(property, MTP_TYPE_UINT32);
+ break;
+ case MTP_PROPERTY_OBJECT_SIZE:
+ result = new MtpProperty(property, MTP_TYPE_UINT64);
+ break;
+ case MTP_PROPERTY_PERSISTENT_UID:
+ result = new MtpProperty(property, MTP_TYPE_UINT128);
+ break;
+ case MTP_PROPERTY_OBJECT_FILE_NAME:
+ case MTP_PROPERTY_DATE_MODIFIED:
+ result = new MtpProperty(property, MTP_TYPE_STR);
+ break;
+ }
+
+ return result;
+}
+
+MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
+ return NULL;
+}
+
#endif // HAVE_ANDROID_OS
// ----------------------------------------------------------------------------
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 798271e..d856eb4 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -17,7 +17,7 @@
#define LOG_TAG "Bundle"
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include <cutils/log.h>
#include <assert.h>
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 2043e44..03f1409 100755
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -17,7 +17,7 @@
#define LOG_TAG "Reverb"
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include <cutils/log.h>
#include <assert.h>
@@ -61,42 +61,81 @@
/* Preset definitions */
/* */
/************************************************************************************/
-LVM_UINT16 RevPreset_Level[] = { 32, 32, 32, 32, 32, 32, 32, 32, 32, 32};
-LVM_UINT16 RevPreset_LPF[] = {1298, 1000, 5012, 3542, 3400, 23999, 2536, 1000, 1000, 1000};
-LVM_UINT16 RevPreset_HPF[] = { 50, 50, 50, 50, 50, 50, 50, 50, 50, 50};
-LVM_UINT16 RevPreset_T60[] = {1490, 500, 2310, 4230, 3920, 2910, 7000, 1490, 1490, 170};
-LVM_UINT16 RevPreset_Density[] = { 100, 100, 100, 100, 100, 100, 100, 100, 100, 100};
-LVM_UINT16 RevPreset_Damping[] = { 54, 10, 64, 59, 70, 100, 33, 54, 21, 10};
-LVM_UINT16 RevPreset_RoomSize[] = { 100, 100, 100, 100, 100, 100, 100, 100, 100, 100};
-/************************************************************************************/
-/* */
-/* Preset definitions */
-/* */
-/************************************************************************************/
-#define REV_PRESET_BATHROOM 0
-#define REV_PRESET_LIVINGROOM 1
-#define REV_PRESET_STONEROOM 2
-#define REV_PRESET_AUDITORIUM 3
-#define REV_PRESET_CONCERTHALL 4
-#define REV_PRESET_CAVE 5
-#define REV_PRESET_ARENA 6
-#define REV_PRESET_FOREST 7
-#define REV_PRESET_MOUNTAINS 8
-#define REV_PRESET_PADDEDCELL 9
+const static t_reverb_settings sReverbPresets[] = {
+ // REVERB_PRESET_NONE: values are unused
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ // REVERB_PRESET_SMALLROOM
+ {-1000, -600, 1100, 830, -400, 5, 500, 10, 1000, 1000},
+ // REVERB_PRESET_MEDIUMROOM
+ {-1000, -600, 1300, 830, -1000, 20, -200, 20, 1000, 1000},
+ // REVERB_PRESET_LARGEROOM
+ {-1000, -600, 1500, 830, -1600, 5, -1000, 40, 1000, 1000},
+ // REVERB_PRESET_MEDIUMHALL
+ {-1000, -600, 1800, 700, -1300, 15, -800, 30, 1000, 1000},
+ // REVERB_PRESET_LARGEHALL
+ {-1000, -600, 1800, 700, -2000, 30, -1400, 60, 1000, 1000},
+ // REVERB_PRESET_PLATE
+ {-1000, -200, 1300, 900, 0, 2, 0, 10, 1000, 750},
+};
-// NXP SW Reverb UUID
-const effect_descriptor_t gReverbDescriptor = {
+
+// NXP SW auxiliary environmental reverb
+const effect_descriptor_t gAuxEnvReverbDescriptor = {
{ 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, { 0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e } },
{ 0x4a387fc0, 0x8ab3, 0x11df, 0x8bad, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } },
EFFECT_API_VERSION,
- (EFFECT_FLAG_TYPE_AUXILIARY | EFFECT_FLAG_INSERT_LAST),
+ EFFECT_FLAG_TYPE_AUXILIARY,
0, // TODO
1,
- "Reverb",
+ "Auxiliary Environmental Reverb",
"NXP Software Ltd.",
};
+// NXP SW insert environmental reverb
+static const effect_descriptor_t gInsertEnvReverbDescriptor = {
+ {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
+ {0xc7a511a0, 0xa3bb, 0x11df, 0x860e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ EFFECT_API_VERSION,
+ EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+ 0, // TODO
+ 1,
+ "Insert Environmental Reverb",
+ "NXP Software Ltd.",
+};
+
+// NXP SW auxiliary preset reverb
+static const effect_descriptor_t gAuxPresetReverbDescriptor = {
+ {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ {0xf29a1400, 0xa3bb, 0x11df, 0x8ddc, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ EFFECT_API_VERSION,
+ EFFECT_FLAG_TYPE_AUXILIARY,
+ 0, // TODO
+ 1,
+ "Auxiliary Preset Reverb",
+ "NXP Software Ltd.",
+};
+
+// NXP SW insert preset reverb
+static const effect_descriptor_t gInsertPresetReverbDescriptor = {
+ {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ {0x172cdf00, 0xa3bc, 0x11df, 0xa72f, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ EFFECT_API_VERSION,
+ EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+ 0, // TODO
+ 1,
+ "Insert Preset Reverb",
+ "NXP Software Ltd.",
+};
+
+// gDescriptors contains pointers to all defined effect descriptor in this library
+static const effect_descriptor_t * const gDescriptors[] = {
+ &gAuxEnvReverbDescriptor,
+ &gInsertEnvReverbDescriptor,
+ &gAuxPresetReverbDescriptor,
+ &gInsertPresetReverbDescriptor
+};
+
struct ReverbContext{
const struct effect_interface_s *itfe;
effect_config_t config;
@@ -114,8 +153,14 @@
FILE *PcmOutPtr;
#endif
LVM_Fs_en SampleRate;
+ bool auxiliary;
+ bool preset;
+ uint16_t curPreset;
+ uint16_t nextPreset;
};
+#define REVERB_DEFAULT_PRESET REVERB_PRESET_MEDIUMROOM
+
//--- local function prototypes
int Reverb_init (ReverbContext *pContext);
void Reverb_free (ReverbContext *pContext);
@@ -125,11 +170,12 @@
void *pParam,
size_t *pValueSize,
void *pValue);
+int Reverb_LoadPreset (ReverbContext *pContext);
/* Effect Library Interface Implementation */
extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects){
LOGV("\n\tEffectQueryNumberEffects start");
- *pNumEffects = 1;
+ *pNumEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
LOGV("\tEffectQueryNumberEffects creating %d effects", *pNumEffects);
LOGV("\tEffectQueryNumberEffects end\n");
return 0;
@@ -142,11 +188,11 @@
LOGV("\tLVM_ERROR : EffectQueryEffect was passed NULL pointer");
return -EINVAL;
}
- if (index > 0){
+ if (index >= sizeof(gDescriptors) / sizeof(const effect_descriptor_t *)) {
LOGV("\tLVM_ERROR : EffectQueryEffect index out of range %d", index);
return -ENOENT;
}
- memcpy(pDescriptor, &gReverbDescriptor, sizeof(effect_descriptor_t));
+ memcpy(pDescriptor, gDescriptors[index], sizeof(effect_descriptor_t));
LOGV("\tEffectQueryEffect end\n");
return 0;
} /* end EffectQueryEffect */
@@ -157,6 +203,8 @@
effect_interface_t *pInterface){
int ret;
int i;
+ int length = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
+ const effect_descriptor_t *desc;
LOGV("\t\nEffectCreate start");
@@ -165,9 +213,16 @@
return -EINVAL;
}
- if (memcmp(uuid, &gReverbDescriptor.uuid, sizeof(effect_uuid_t)) != 0){
- LOGV("\tLVM_ERROR : EffectCreate() invalid UUID");
- return -EINVAL;
+ for (i = 0; i < length; i++) {
+ desc = gDescriptors[i];
+ if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t))
+ == 0) {
+ break;
+ }
+ }
+
+ if (i == length) {
+ return -ENOENT;
}
ReverbContext *pContext = new ReverbContext;
@@ -175,6 +230,19 @@
pContext->itfe = &gReverbInterface;
pContext->hInstance = NULL;
+ pContext->auxiliary = false;
+ if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY){
+ pContext->auxiliary = true;
+ }
+
+ pContext->preset = false;
+ if (memcmp(&desc->type, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
+ pContext->preset = true;
+ // force reloading preset at first call to process()
+ pContext->curPreset = REVERB_PRESET_LAST + 1;
+ pContext->nextPreset = REVERB_DEFAULT_PRESET;
+ }
+
LOGV("\tEffectCreate - Calling Reverb_init");
ret = Reverb_init(pContext);
@@ -288,6 +356,14 @@
return;
}
+
+static inline int16_t clamp16(int32_t sample)
+{
+ if ((sample>>15) ^ (sample>>31))
+ sample = 0x7FFF ^ (sample>>31);
+ return sample;
+}
+
//----------------------------------------------------------------------------
// process()
//----------------------------------------------------------------------------
@@ -344,6 +420,9 @@
fflush(pContext->PcmInPtr);
#endif
+ if (pContext->preset && pContext->nextPreset != pContext->curPreset) {
+ Reverb_LoadPreset(pContext);
+ }
// Convert to Input 32 bits
for(int i=0; i<frameCount*samplesPerFrame; i++){
InFrames32[i] = (LVM_INT32)pIn[i]<<8;
@@ -359,18 +438,28 @@
//frameCount, pContext->config.inputCfg.channels, CHANNEL_MONO,
//pContext->config.outputCfg.channels, CHANNEL_STEREO);
+ if (pContext->preset && pContext->curPreset == REVERB_PRESET_NONE) {
+ memset(OutFrames32, 0, frameCount * sizeof(LVM_INT32) * 2);
+ } else {
/* Process the samples */
LvmStatus = LVREV_Process(pContext->hInstance, /* Instance handle */
InFrames32, /* Input buffer */
OutFrames32, /* Output buffer */
frameCount); /* Number of samples to read */
+ }
+
+ if (!pContext->auxiliary) {
+ for (int i=0; i<frameCount*2; i++){
+ OutFrames32[i] += InFrames32[i];
+ }
+ }
LVM_ERROR_CHECK(LvmStatus, "LVREV_Process", "process")
if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
// Convert to 16 bits
for(int i=0; i<frameCount*2; i++){ // Always stereo
- OutFrames16[i] = (LVM_INT16)(OutFrames32[i]>>8);
+ OutFrames16[i] = clamp16(OutFrames32[i]>>8);
}
#ifdef LVM_PCM
@@ -382,7 +471,7 @@
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
//LOGV("\tBuffer access is ACCUMULATE");
for (int i=0; i<frameCount*2; i++){
- pOut[i] += OutFrames16[i];
+ pOut[i] = clamp16((int32_t)pOut[i] + (int32_t)OutFrames16[i]);
}
}else{
//LOGV("\tBuffer access is WRITE");
@@ -462,6 +551,8 @@
CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
+ CHECK_ARG((pContext->auxiliary && pConfig->inputCfg.channels == CHANNEL_MONO) ||
+ ((!pContext->auxiliary) && pConfig->inputCfg.channels == CHANNEL_STEREO));
CHECK_ARG(pConfig->outputCfg.channels == CHANNEL_STEREO);
CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
|| pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
@@ -540,18 +631,8 @@
int Reverb_init(ReverbContext *pContext){
int status;
- int channel_mode;
- LOGV("\tReverb_init start %d", gReverbDescriptor.flags);
-
- if((gReverbDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT){
- LOGV("\tReverb_init EFFECT_FLAG_TYPE_INSERT");
- channel_mode = CHANNEL_STEREO;
- }
- if((gReverbDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY ){
- LOGV("\tReverb_init EFFECT_FLAG_TYPE_AUXILIARY");
- channel_mode = CHANNEL_MONO;
- }
+ LOGV("\tReverb_init start");
CHECK_ARG(pContext != NULL);
@@ -560,7 +641,12 @@
}
pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
- pContext->config.inputCfg.channels = channel_mode;
+ if (pContext->auxiliary) {
+ pContext->config.inputCfg.channels = CHANNEL_MONO;
+ } else {
+ pContext->config.inputCfg.channels = CHANNEL_STEREO;
+ }
+
pContext->config.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
pContext->config.inputCfg.samplingRate = 44100;
pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
@@ -653,11 +739,11 @@
/* Reverb parameters */
params.Level = 0;
params.LPF = 23999;
- params.HPF = RevPreset_HPF[REV_PRESET_MOUNTAINS];
- params.T60 = RevPreset_T60[REV_PRESET_MOUNTAINS];
- params.Density = RevPreset_Density[REV_PRESET_MOUNTAINS];
- params.Damping = RevPreset_Damping[REV_PRESET_MOUNTAINS];
- params.RoomSize = RevPreset_RoomSize[REV_PRESET_MOUNTAINS];
+ params.HPF = 50;
+ params.T60 = 1490;
+ params.Density = 100;
+ params.Damping = 21;
+ params.RoomSize = 100;
/* Saved strength is used to return the exact strength that was used in the set to the get
* because we map the original strength range of 0:1000 to 1:15, and this will avoid
@@ -1294,6 +1380,44 @@
}
//----------------------------------------------------------------------------
+// Reverb_LoadPreset()
+//----------------------------------------------------------------------------
+// Purpose:
+// Load a the next preset
+//
+// Inputs:
+// pContext - handle to instance data
+//
+// Outputs:
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+int Reverb_LoadPreset(ReverbContext *pContext)
+{
+ //TODO: add reflections delay, level and reverb delay when early reflections are
+ // implemented
+ pContext->curPreset = pContext->nextPreset;
+
+ if (pContext->curPreset != REVERB_PRESET_NONE) {
+ const t_reverb_settings *preset = &sReverbPresets[pContext->curPreset];
+ ReverbSetRoomLevel(pContext, preset->roomLevel);
+ ReverbSetRoomHfLevel(pContext, preset->roomHFLevel);
+ ReverbSetDecayTime(pContext, preset->decayTime);
+ ReverbSetDecayHfRatio(pContext, preset->decayHFRatio);
+ //reflectionsLevel
+ //reflectionsDelay
+ ReverbSetReverbLevel(pContext, preset->reverbLevel);
+ // reverbDelay
+ ReverbSetDiffusion(pContext, preset->diffusion);
+ ReverbSetDensity(pContext, preset->density);
+ }
+
+ return 0;
+}
+
+
+//----------------------------------------------------------------------------
// Reverb_getParameter()
//----------------------------------------------------------------------------
// Purpose:
@@ -1325,6 +1449,15 @@
t_reverb_settings *pProperties;
//LOGV("\tReverb_getParameter start");
+ if (pContext->preset) {
+ if (param != REVERB_PARAM_PRESET || *pValueSize < sizeof(uint16_t)) {
+ return -EINVAL;
+ }
+
+ *(uint16_t *)pValue = pContext->nextPreset;
+ LOGV("get REVERB_PARAM_PRESET, preset %d", pContext->nextPreset);
+ return 0;
+ }
switch (param){
case REVERB_PARAM_ROOM_LEVEL:
@@ -1531,6 +1664,18 @@
int32_t param = *pParamTemp++;
//LOGV("\tReverb_setParameter start");
+ if (pContext->preset) {
+ if (param != REVERB_PARAM_PRESET) {
+ return -EINVAL;
+ }
+
+ uint16_t preset = *(uint16_t *)pValue;
+ LOGV("set REVERB_PARAM_PRESET, preset %d", preset);
+ if (preset > REVERB_PRESET_LAST) {
+ return -EINVAL;
+ }
+ pContext->nextPreset = preset;
+ }
switch (param){
case REVERB_PARAM_PROPERTIES:
diff --git a/media/libmedia/fixedfft.cpp b/media/libmedia/fixedfft.cpp
index 28eb05a..9cf05ba 100644
--- a/media/libmedia/fixedfft.cpp
+++ b/media/libmedia/fixedfft.cpp
@@ -26,7 +26,9 @@
#include <stdio.h>
#include <stdint.h>
+#ifdef __ARM_ARCH__
#include <machine/cpu-features.h>
+#endif
#define LOG_FFT_SIZE 10
#define MAX_FFT_SIZE (1 << LOG_FFT_SIZE)
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
index 70af2da..1b05528 100644
--- a/media/libstagefright/AMRExtractor.cpp
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -87,7 +87,7 @@
mInitCheck(NO_INIT) {
String8 mimeType;
float confidence;
- if (!SniffAMR(mDataSource, &mimeType, &confidence)) {
+ if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) {
return;
}
@@ -276,7 +276,8 @@
////////////////////////////////////////////////////////////////////////////////
bool SniffAMR(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
char header[9];
if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index e167afa..1ccfa03 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -461,27 +461,34 @@
return;
}
+ bool eos;
+ size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
+
size_t lowWatermark = 400000;
size_t highWatermark = 1000000;
- off_t size;
- if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
- int64_t bitrate = size * 8000000ll / mDurationUs; // in bits/sec
+ if (eos) {
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
+ } else {
+ off_t size;
+ if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
+ int64_t bitrate = size * 8000000ll / mDurationUs; // in bits/sec
- size_t cachedSize = mCachedSource->cachedSize();
- int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
+ size_t cachedSize = mCachedSource->cachedSize();
+ int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
- double percentage = (double)cachedDurationUs / mDurationUs;
+ int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
+ if (percentage > 100) {
+ percentage = 100;
+ }
- notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
- lowWatermark = 2 * bitrate / 8; // 2 secs
- highWatermark = 10 * bitrate / 8; // 10 secs
+ lowWatermark = 2 * bitrate / 8; // 2 secs
+ highWatermark = 10 * bitrate / 8; // 10 secs
+ }
}
- bool eos;
- size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
-
if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < lowWatermark)) {
LOGI("cache is running low (< %d) , pausing.", lowWatermark);
mFlags |= CACHE_UNDERRUN;
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 90a596c..49eac62 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -25,6 +25,7 @@
#include "matroska/MatroskaExtractor.h"
+#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/FileSource.h>
#include <media/stagefright/MediaErrors.h>
@@ -56,19 +57,23 @@
Mutex DataSource::gSnifferMutex;
List<DataSource::SnifferFunc> DataSource::gSniffers;
-bool DataSource::sniff(String8 *mimeType, float *confidence) {
+bool DataSource::sniff(
+ String8 *mimeType, float *confidence, sp<AMessage> *meta) {
*mimeType = "";
*confidence = 0.0f;
+ meta->clear();
Mutex::Autolock autoLock(gSnifferMutex);
for (List<SnifferFunc>::iterator it = gSniffers.begin();
it != gSniffers.end(); ++it) {
String8 newMimeType;
float newConfidence;
- if ((*it)(this, &newMimeType, &newConfidence)) {
+ sp<AMessage> newMeta;
+ if ((*it)(this, &newMimeType, &newConfidence, &newMeta)) {
if (newConfidence > *confidence) {
*mimeType = newMimeType;
*confidence = newConfidence;
+ *meta = newMeta;
}
}
}
@@ -92,13 +97,13 @@
// static
void DataSource::RegisterDefaultSniffers() {
- RegisterSniffer(SniffMP3);
RegisterSniffer(SniffMPEG4);
- RegisterSniffer(SniffAMR);
- RegisterSniffer(SniffWAV);
- RegisterSniffer(SniffOgg);
RegisterSniffer(SniffMatroska);
+ RegisterSniffer(SniffOgg);
+ RegisterSniffer(SniffWAV);
+ RegisterSniffer(SniffAMR);
RegisterSniffer(SniffMPEG2TS);
+ RegisterSniffer(SniffMP3);
}
// static
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 4058fbc..2e36968 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -22,6 +22,7 @@
#include "include/ID3.h"
+#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
@@ -456,15 +457,31 @@
MP3Source &operator=(const MP3Source &);
};
-MP3Extractor::MP3Extractor(const sp<DataSource> &source)
+MP3Extractor::MP3Extractor(
+ const sp<DataSource> &source, const sp<AMessage> &meta)
: mDataSource(source),
mFirstFramePos(-1),
mFixedHeader(0),
mByteNumber(0) {
off_t pos = 0;
uint32_t header;
- bool success = Resync(mDataSource, 0, &pos, &header);
- CHECK(success);
+ bool success;
+
+ int64_t meta_offset;
+ uint32_t meta_header;
+ if (meta != NULL
+ && meta->findInt64("offset", &meta_offset)
+ && meta->findInt32("header", (int32_t *)&meta_header)) {
+ // The sniffer has already done all the hard work for us, simply
+ // accept its judgement.
+ pos = (off_t)meta_offset;
+ header = meta_header;
+
+ success = true;
+ } else {
+ success = Resync(mDataSource, 0, &pos, &header);
+ CHECK(success);
+ }
if (success) {
mFirstFramePos = pos;
@@ -759,15 +776,20 @@
}
bool SniffMP3(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType,
+ float *confidence, sp<AMessage> *meta) {
off_t pos = 0;
uint32_t header;
if (!Resync(source, 0, &pos, &header)) {
return false;
}
+ *meta = new AMessage;
+ (*meta)->setInt64("offset", pos);
+ (*meta)->setInt32("header", header);
+
*mimeType = MEDIA_MIMETYPE_AUDIO_MPEG;
- *confidence = 0.3f;
+ *confidence = 0.2f;
return true;
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 12a1e6e..ba90407 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1738,7 +1738,7 @@
|| !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
|| !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
- *confidence = 0.1;
+ *confidence = 0.4;
return true;
}
@@ -1805,13 +1805,14 @@
}
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
- *confidence = 0.3f;
+ *confidence = 0.4f;
return true;
}
bool SniffMPEG4(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
if (BetterSniffMPEG4(source, mimeType, confidence)) {
return true;
}
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index e36d9fe..a15b84e 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1569,9 +1569,9 @@
// The idea here is to avoid having two or more samples with the
// same timestamp in the output file.
if (mTimeScale >= 1000000LL) {
- timestampUs += 1;
+ timestampUs = lastTimestampUs + 1;
} else {
- timestampUs += (1000000LL + (mTimeScale >> 1)) / mTimeScale;
+ timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale;
}
#endif
}
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 56e6136..9bc94de 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -27,6 +27,7 @@
#include "matroska/MatroskaExtractor.h"
+#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaExtractor.h>
@@ -46,10 +47,12 @@
// static
sp<MediaExtractor> MediaExtractor::Create(
const sp<DataSource> &source, const char *mime) {
+ sp<AMessage> meta;
+
String8 tmp;
if (mime == NULL) {
float confidence;
- if (!source->sniff(&tmp, &confidence)) {
+ if (!source->sniff(&tmp, &confidence, &meta)) {
LOGV("FAILED to autodetect media content.");
return NULL;
@@ -64,7 +67,7 @@
|| !strcasecmp(mime, "audio/mp4")) {
return new MPEG4Extractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
- return new MP3Extractor(source);
+ return new MP3Extractor(source, meta);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)
|| !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
return new AMRExtractor(source);
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 9630092..2c1311a 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -804,7 +804,8 @@
}
bool SniffOgg(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
char tmp[4];
if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
return false;
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index 8d820c0..57c1075 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -404,7 +404,8 @@
////////////////////////////////////////////////////////////////////////////////
bool SniffWAV(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
char header[12];
if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
return false;
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index ca0c68c..da340f7 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -142,11 +142,22 @@
mSize = size;
if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) {
+ free(mData);
+ mData = NULL;
+
return false;
}
- if (header.flags & 0x80) {
+ if (header.version_major == 4) {
+ if (!removeUnsynchronizationV2_4()) {
+ free(mData);
+ mData = NULL;
+
+ return false;
+ }
+ } else if (header.flags & 0x80) {
LOGV("removing unsynchronization");
+
removeUnsynchronization();
}
@@ -243,6 +254,74 @@
}
}
+static void WriteSyncsafeInteger(uint8_t *dst, size_t x) {
+ for (size_t i = 0; i < 4; ++i) {
+ dst[3 - i] = (x & 0x7f);
+ x >>= 7;
+ }
+}
+
+bool ID3::removeUnsynchronizationV2_4() {
+ size_t oldSize = mSize;
+
+ size_t offset = 0;
+ while (offset + 10 <= mSize) {
+ if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
+ break;
+ }
+
+ size_t dataSize;
+ if (!ParseSyncsafeInteger(&mData[offset + 4], &dataSize)) {
+ return false;
+ }
+
+ if (offset + dataSize + 10 > mSize) {
+ return false;
+ }
+
+ uint16_t flags = U16_AT(&mData[offset + 8]);
+ uint16_t prevFlags = flags;
+
+ if (flags & 1) {
+ // Strip data length indicator
+
+ memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14);
+ mSize -= 4;
+ dataSize -= 4;
+
+ flags &= ~1;
+ }
+
+ if (flags & 2) {
+ // Unsynchronization added.
+
+ for (size_t i = 0; i + 1 < dataSize; ++i) {
+ if (mData[offset + 10 + i] == 0xff
+ && mData[offset + 11 + i] == 0x00) {
+ memmove(&mData[offset + 11 + i], &mData[offset + 12 + i],
+ mSize - offset - 12 - i);
+ --mSize;
+ --dataSize;
+ }
+ }
+
+ flags &= ~2;
+ }
+
+ if (flags != prevFlags) {
+ WriteSyncsafeInteger(&mData[offset + 4], dataSize);
+ mData[offset + 8] = flags >> 8;
+ mData[offset + 9] = flags & 0xff;
+ }
+
+ offset += 10 + dataSize;
+ }
+
+ memset(&mData[mSize], 0, oldSize - mSize);
+
+ return true;
+}
+
ID3::Iterator::Iterator(const ID3 &parent, const char *id)
: mParent(parent),
mID(NULL),
@@ -529,10 +608,11 @@
uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]);
- if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000e))
+ if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000c))
|| (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) {
- // Compression, Encryption or per-Frame unsynchronization
- // are not supported at this time.
+ // Compression or encryption are not supported at this time.
+ // Per-frame unsynchronization and data-length indicator
+ // have already been taken care of.
LOGV("Skipping unsupported frame (compression, encryption "
"or per-frame unsynchronization flagged");
diff --git a/media/libstagefright/include/AMRExtractor.h b/media/libstagefright/include/AMRExtractor.h
index db49fe4..1cdf36d 100644
--- a/media/libstagefright/include/AMRExtractor.h
+++ b/media/libstagefright/include/AMRExtractor.h
@@ -22,6 +22,7 @@
namespace android {
+struct AMessage;
class String8;
class AMRExtractor : public MediaExtractor {
@@ -49,7 +50,8 @@
};
bool SniffAMR(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
} // namespace android
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
index c6b1a8b..7ddbb41 100644
--- a/media/libstagefright/include/ID3.h
+++ b/media/libstagefright/include/ID3.h
@@ -80,6 +80,7 @@
bool parseV1(const sp<DataSource> &source);
bool parseV2(const sp<DataSource> &source);
void removeUnsynchronization();
+ bool removeUnsynchronizationV2_4();
static bool ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x);
diff --git a/media/libstagefright/include/MP3Extractor.h b/media/libstagefright/include/MP3Extractor.h
index 3ce6df3..0e6ccde 100644
--- a/media/libstagefright/include/MP3Extractor.h
+++ b/media/libstagefright/include/MP3Extractor.h
@@ -22,13 +22,14 @@
namespace android {
+struct AMessage;
class DataSource;
class String8;
class MP3Extractor : public MediaExtractor {
public:
// Extractor assumes ownership of "source".
- MP3Extractor(const sp<DataSource> &source);
+ MP3Extractor(const sp<DataSource> &source, const sp<AMessage> &meta);
virtual size_t countTracks();
virtual sp<MediaSource> getTrack(size_t index);
@@ -52,7 +53,8 @@
};
bool SniffMP3(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *meta);
} // namespace android
diff --git a/media/libstagefright/include/MPEG2TSExtractor.h b/media/libstagefright/include/MPEG2TSExtractor.h
index c96973b..1bf4cd1 100644
--- a/media/libstagefright/include/MPEG2TSExtractor.h
+++ b/media/libstagefright/include/MPEG2TSExtractor.h
@@ -9,6 +9,7 @@
namespace android {
+struct AMessage;
struct AnotherPacketSource;
struct ATSParser;
struct DataSource;
@@ -47,7 +48,8 @@
};
bool SniffMPEG2TS(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
} // namespace android
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index c8663d5..1c9cc7e 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -23,6 +23,7 @@
namespace android {
+struct AMessage;
class DataSource;
class SampleTable;
class String8;
@@ -75,7 +76,8 @@
};
bool SniffMPEG4(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
} // namespace android
diff --git a/media/libstagefright/include/OggExtractor.h b/media/libstagefright/include/OggExtractor.h
index 7066669..1eda025 100644
--- a/media/libstagefright/include/OggExtractor.h
+++ b/media/libstagefright/include/OggExtractor.h
@@ -22,6 +22,7 @@
namespace android {
+struct AMessage;
class DataSource;
class String8;
@@ -53,7 +54,8 @@
};
bool SniffOgg(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
} // namespace android
diff --git a/media/libstagefright/include/WAVExtractor.h b/media/libstagefright/include/WAVExtractor.h
index 3e847b9..df6d3e7 100644
--- a/media/libstagefright/include/WAVExtractor.h
+++ b/media/libstagefright/include/WAVExtractor.h
@@ -22,6 +22,7 @@
namespace android {
+struct AMessage;
class DataSource;
class String8;
@@ -58,7 +59,8 @@
};
bool SniffWAV(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
} // namespace android
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 71f6587..7c7d69e 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -579,7 +579,8 @@
}
bool SniffMatroska(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
DataSourceReader reader(source);
mkvparser::EBMLHeader ebmlHeader;
long long pos;
diff --git a/media/libstagefright/matroska/MatroskaExtractor.h b/media/libstagefright/matroska/MatroskaExtractor.h
index 7471848..fa20b84 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.h
+++ b/media/libstagefright/matroska/MatroskaExtractor.h
@@ -27,6 +27,7 @@
namespace android {
+struct AMessage;
class String8;
struct DataSourceReader;
@@ -69,7 +70,8 @@
};
bool SniffMatroska(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
} // namespace android
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
index b287c95..56ca375 100644
--- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -174,7 +174,8 @@
////////////////////////////////////////////////////////////////////////////////
bool SniffMPEG2TS(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
#if 0
char header;
if (source->readAt(0, &header, 1) != 1 || header != 0x47) {
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 27dc796..ec78ff0 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -242,6 +242,16 @@
putUInt32(value[3]);
}
+void MtpDataPacket::putInt128(int64_t value) {
+ putInt64(value);
+ putInt64(value < 0 ? -1 : 0);
+}
+
+void MtpDataPacket::putUInt128(uint64_t value) {
+ putUInt64(value);
+ putUInt64(0);
+}
+
void MtpDataPacket::putAInt8(const int8_t* values, int count) {
putUInt32(count);
for (int i = 0; i < count; i++)
@@ -363,7 +373,7 @@
int MtpDataPacket::write(int fd) {
MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
-
+ dump();
// send header separately from data
int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
if (ret == MTP_CONTAINER_HEADER_SIZE)
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 1467aab..fab6a07 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -69,6 +69,8 @@
void putUInt64(uint64_t value);
void putInt128(const int128_t& value);
void putUInt128(const uint128_t& value);
+ void putInt128(int64_t value);
+ void putUInt128(uint64_t value);
void putAInt8(const int8_t* values, int count);
void putAUInt8(const uint8_t* values, int count);
diff --git a/media/mtp/MtpDatabase.h b/media/mtp/MtpDatabase.h
index 17823df..899b34a 100644
--- a/media/mtp/MtpDatabase.h
+++ b/media/mtp/MtpDatabase.h
@@ -22,6 +22,7 @@
namespace android {
class MtpDataPacket;
+class MtpProperty;
class MtpDatabase {
public:
@@ -58,10 +59,22 @@
virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format) = 0;
virtual MtpDevicePropertyList* getSupportedDeviceProperties() = 0;
- virtual MtpResponseCode getObjectProperty(MtpObjectHandle handle,
+ virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle,
MtpObjectProperty property,
MtpDataPacket& packet) = 0;
+ virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle,
+ MtpObjectProperty property,
+ MtpDataPacket& packet) = 0;
+
+ virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property,
+ MtpDataPacket& packet) = 0;
+
+ virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property,
+ MtpDataPacket& packet) = 0;
+
+ virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property) = 0;
+
virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
MtpDataPacket& packet) = 0;
@@ -76,6 +89,10 @@
virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
MtpObjectHandleList* references) = 0;
+ virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
+ MtpObjectFormat format) = 0;
+
+ virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property) = 0;
};
}; // namespace android
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 30abfb8..1e64e4f 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -56,17 +56,17 @@
// MTP_OPERATION_SET_OBJECT_PROTECTION,
// MTP_OPERATION_POWER_DOWN,
// MTP_OPERATION_GET_DEVICE_PROP_DESC,
-// MTP_OPERATION_GET_DEVICE_PROP_VALUE,
-// MTP_OPERATION_SET_DEVICE_PROP_VALUE,
-// MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
+ MTP_OPERATION_GET_DEVICE_PROP_VALUE,
+ MTP_OPERATION_SET_DEVICE_PROP_VALUE,
+ MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
// MTP_OPERATION_TERMINATE_OPEN_CAPTURE,
// MTP_OPERATION_MOVE_OBJECT,
// MTP_OPERATION_COPY_OBJECT,
// MTP_OPERATION_GET_PARTIAL_OBJECT,
// MTP_OPERATION_INITIATE_OPEN_CAPTURE,
MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED,
-// MTP_OPERATION_GET_OBJECT_PROP_DESC,
- MTP_OPERATION_GET_OBJECT_PROP_VALUE,
+ MTP_OPERATION_GET_OBJECT_PROP_DESC,
+// MTP_OPERATION_GET_OBJECT_PROP_VALUE,
// MTP_OPERATION_SET_OBJECT_PROP_VALUE,
MTP_OPERATION_GET_OBJECT_REFERENCES,
MTP_OPERATION_SET_OBJECT_REFERENCES,
@@ -91,7 +91,6 @@
mSendObjectFormat(0),
mSendObjectFileSize(0)
{
- initObjectProperties();
}
MtpServer::~MtpServer() {
@@ -136,7 +135,9 @@
// FIXME need to generalize this
bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO
- || operation == MTP_OPERATION_SET_OBJECT_REFERENCES);
+ || operation == MTP_OPERATION_SET_OBJECT_REFERENCES
+ || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE
+ || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE);
if (dataIn) {
int ret = mData.read(fd);
if (ret < 0) {
@@ -158,7 +159,6 @@
mData.setOperationCode(operation);
mData.setTransactionID(transaction);
LOGV("sending data:");
- mData.dump();
ret = mData.write(fd);
if (ret < 0) {
LOGE("request write returned %d, errno: %d", ret, errno);
@@ -187,24 +187,6 @@
}
}
-MtpProperty* MtpServer::getObjectProperty(MtpPropertyCode propCode) {
- for (int i = 0; i < mObjectProperties.size(); i++) {
- MtpProperty* property = mObjectProperties[i];
- if (property->getPropertyCode() == propCode)
- return property;
- }
- return NULL;
-}
-
-MtpProperty* MtpServer::getDeviceProperty(MtpPropertyCode propCode) {
- for (int i = 0; i < mDeviceProperties.size(); i++) {
- MtpProperty* property = mDeviceProperties[i];
- if (property->getPropertyCode() == propCode)
- return property;
- }
- return NULL;
-}
-
void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
if (mSessionOpen) {
LOGD("sendObjectAdded %d\n", handle);
@@ -227,14 +209,6 @@
}
}
-void MtpServer::initObjectProperties() {
- mObjectProperties.push(new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32));
- mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16));
- mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64));
- mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR));
- mObjectProperties.push(new MtpProperty(MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32));
-}
-
bool MtpServer::handleRequest() {
MtpOperationCode operation = mRequest.getOperationCode();
MtpResponseCode response;
@@ -281,6 +255,18 @@
case MTP_OPERATION_GET_OBJECT_PROP_VALUE:
response = doGetObjectPropValue();
break;
+ case MTP_OPERATION_SET_OBJECT_PROP_VALUE:
+ response = doSetObjectPropValue();
+ break;
+ case MTP_OPERATION_GET_DEVICE_PROP_VALUE:
+ response = doGetDevicePropValue();
+ break;
+ case MTP_OPERATION_SET_DEVICE_PROP_VALUE:
+ response = doSetDevicePropValue();
+ break;
+ case MTP_OPERATION_RESET_DEVICE_PROP_VALUE:
+ response = doResetDevicePropValue();
+ break;
case MTP_OPERATION_GET_OBJECT_INFO:
response = doGetObjectInfo();
break;
@@ -456,13 +442,15 @@
if (!mSessionOpen)
return MTP_RESPONSE_SESSION_NOT_OPEN;
MtpStorageID handle = mRequest.getParameter(1);
+
+ // FIXME - check for invalid object handle
MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle);
- if (!handles) {
+ if (handles) {
+ mData.putAUInt32(handles);
+ delete handles;
+ } else {
mData.putEmptyArray();
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
}
- mData.putAUInt32(handles);
- delete handles;
return MTP_RESPONSE_OK;
}
@@ -479,8 +467,43 @@
MtpResponseCode MtpServer::doGetObjectPropValue() {
MtpObjectHandle handle = mRequest.getParameter(1);
MtpObjectProperty property = mRequest.getParameter(2);
+ LOGD("GetObjectPropValue %d %s\n", handle,
+ MtpDebug::getObjectPropCodeName(property));
- return mDatabase->getObjectProperty(handle, property, mData);
+ return mDatabase->getObjectPropertyValue(handle, property, mData);
+}
+
+MtpResponseCode MtpServer::doSetObjectPropValue() {
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ MtpObjectProperty property = mRequest.getParameter(2);
+ LOGD("SetObjectPropValue %d %s\n", handle,
+ MtpDebug::getObjectPropCodeName(property));
+
+ return mDatabase->setObjectPropertyValue(handle, property, mData);
+}
+
+MtpResponseCode MtpServer::doGetDevicePropValue() {
+ MtpDeviceProperty property = mRequest.getParameter(1);
+ LOGD("GetDevicePropValue %s\n",
+ MtpDebug::getDevicePropCodeName(property));
+
+ return mDatabase->getDevicePropertyValue(property, mData);
+}
+
+MtpResponseCode MtpServer::doSetDevicePropValue() {
+ MtpDeviceProperty property = mRequest.getParameter(1);
+ LOGD("SetDevicePropValue %s\n",
+ MtpDebug::getDevicePropCodeName(property));
+
+ return mDatabase->setDevicePropertyValue(property, mData);
+}
+
+MtpResponseCode MtpServer::doResetDevicePropValue() {
+ MtpDeviceProperty property = mRequest.getParameter(1);
+ LOGD("ResetDevicePropValue %s\n",
+ MtpDebug::getDevicePropCodeName(property));
+
+ return mDatabase->resetDeviceProperty(property);
}
MtpResponseCode MtpServer::doGetObjectInfo() {
@@ -592,7 +615,7 @@
}
mResponse.setParameter(1, storageID);
- mResponse.setParameter(2, (parent == 0 ? 0xFFFFFFFF: parent));
+ mResponse.setParameter(2, parent);
mResponse.setParameter(3, handle);
return MTP_RESPONSE_OK;
@@ -677,11 +700,24 @@
MtpResponseCode MtpServer::doGetObjectPropDesc() {
MtpObjectProperty propCode = mRequest.getParameter(1);
MtpObjectFormat format = mRequest.getParameter(2);
- MtpProperty* property = getObjectProperty(propCode);
+ LOGD("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode),
+ MtpDebug::getFormatCodeName(format));
+ MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format);
if (!property)
return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
-
property->write(mData);
+ delete property;
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doGetDevicePropDesc() {
+ MtpDeviceProperty propCode = mRequest.getParameter(1);
+ LOGD("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode));
+ MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode);
+ if (!property)
+ return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+ property->write(mData);
+ delete property;
return MTP_RESPONSE_OK;
}
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
index 19ccf24..68a6564 100644
--- a/media/mtp/MtpServer.h
+++ b/media/mtp/MtpServer.h
@@ -28,7 +28,6 @@
namespace android {
class MtpDatabase;
-class MtpProperty;
class MtpStorage;
class MtpServer {
@@ -57,9 +56,6 @@
MtpStorageList mStorages;
- MtpPropertyList mObjectProperties;
- MtpPropertyList mDeviceProperties;
-
// handle for new object, set by SendObjectInfo and used by SendObject
MtpObjectHandle mSendObjectHandle;
MtpObjectFormat mSendObjectFormat;
@@ -76,15 +72,10 @@
MtpStorage* getStorage(MtpStorageID id);
void run();
- MtpProperty* getObjectProperty(MtpPropertyCode propCode);
- MtpProperty* getDeviceProperty(MtpPropertyCode propCode);
-
void sendObjectAdded(MtpObjectHandle handle);
void sendObjectRemoved(MtpObjectHandle handle);
private:
- void initObjectProperties();
-
bool handleRequest();
MtpResponseCode doGetDeviceInfo();
@@ -98,12 +89,17 @@
MtpResponseCode doGetObjectReferences();
MtpResponseCode doSetObjectReferences();
MtpResponseCode doGetObjectPropValue();
+ MtpResponseCode doSetObjectPropValue();
+ MtpResponseCode doGetDevicePropValue();
+ MtpResponseCode doSetDevicePropValue();
+ MtpResponseCode doResetDevicePropValue();
MtpResponseCode doGetObjectInfo();
MtpResponseCode doGetObject();
MtpResponseCode doSendObjectInfo();
MtpResponseCode doSendObject();
MtpResponseCode doDeleteObject();
MtpResponseCode doGetObjectPropDesc();
+ MtpResponseCode doGetDevicePropDesc();
};
}; // namespace android
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
index c7f461e..46135ff 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
@@ -27,7 +27,9 @@
import com.android.mediaframeworktest.functional.MediaAudioManagerTest;
import com.android.mediaframeworktest.functional.MediaAudioEffectTest;
import com.android.mediaframeworktest.functional.MediaBassBoostTest;
+import com.android.mediaframeworktest.functional.MediaEnvReverbTest;
import com.android.mediaframeworktest.functional.MediaEqualizerTest;
+import com.android.mediaframeworktest.functional.MediaPresetReverbTest;
import com.android.mediaframeworktest.functional.MediaVirtualizerTest;
import com.android.mediaframeworktest.functional.MediaVisualizerTest;
import junit.framework.TestSuite;
@@ -62,7 +64,9 @@
suite.addTestSuite(MediaAudioManagerTest.class);
suite.addTestSuite(MediaAudioEffectTest.class);
suite.addTestSuite(MediaBassBoostTest.class);
+ suite.addTestSuite(MediaEnvReverbTest.class);
suite.addTestSuite(MediaEqualizerTest.class);
+ suite.addTestSuite(MediaPresetReverbTest.class);
suite.addTestSuite(MediaVirtualizerTest.class);
suite.addTestSuite(MediaVisualizerTest.class);
return suite;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/EnergyProbe.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/EnergyProbe.java
new file mode 100644
index 0000000..d339e06
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/EnergyProbe.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 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.mediaframeworktest.functional;
+
+import android.media.Visualizer;
+import android.util.Log;
+
+/**
+ * The EnergyProbe class provides audio signal energy measurements based on the FFT returned
+ * by the Visualizer class. The measure is qualitative and not quantitative in that the returned
+ * value has no unit and is just proportional to the amount of energy present around the
+ * specified frequency.
+ */
+
+public class EnergyProbe {
+ private String TAG = "EnergyProbe";
+
+ private static int CAPTURE_SIZE = 1024;
+ private static int MEASURE_COUNT = 5;
+ private static int AVERAGE_COUNT = 3;
+
+ private Visualizer mVisualizer = null;
+ private int mMaxFrequency = 0;
+ private int mCapturePeriodMs;
+ private byte[] mFft = new byte[CAPTURE_SIZE];
+
+ public EnergyProbe(int session) {
+ try {
+ mVisualizer = new Visualizer(session);
+ if (mVisualizer != null) {
+ mVisualizer.setCaptureSize(CAPTURE_SIZE);
+ mMaxFrequency = mVisualizer.getSamplingRate() / 2000;
+ mCapturePeriodMs = 1000000 / mVisualizer.getMaxCaptureRate();
+ }
+ } catch (UnsupportedOperationException e) {
+ Log.e(TAG, "Error creating visualizer");
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Error configuring visualizer");
+ }
+ }
+
+ public int capture(int freq) throws InterruptedException {
+ int energy = 0;
+ int count = 0;
+
+ if (freq > mMaxFrequency) {
+ return 0;
+ }
+
+ if (mVisualizer != null) {
+ try {
+ mVisualizer.setEnabled(true);
+ for (int i = 0; i < MEASURE_COUNT; i++) {
+ if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) {
+ if (freq == mMaxFrequency) {
+ energy += (int)mFft[0] * (int)mFft[0];
+ } else {
+ int bin = 2 * (freq * CAPTURE_SIZE / mMaxFrequency / 2);
+ if (bin < 2) bin = 2;
+ int tmp = 0;
+ int j;
+ for (j = 0;
+ (j < AVERAGE_COUNT) && ((bin + 2 * j) < CAPTURE_SIZE);
+ j++) {
+ tmp += (int)mFft[bin + 2 * j] * (int)mFft[bin + 2 * j] +
+ (int)mFft[bin + 2 * j + 1] * (int)mFft[bin + 2 * j + 1];
+ }
+ // j is always != 0
+ energy += tmp/j;
+ }
+ count++;
+ }
+ Thread.sleep(mCapturePeriodMs);
+ }
+ mVisualizer.setEnabled(false);
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Error capturing audio");
+ }
+ }
+ if (count == 0) {
+ return 0;
+ }
+ return energy/count;
+ }
+
+ public void release() {
+ if (mVisualizer != null) {
+ mVisualizer.release();
+ mVisualizer = null;
+ }
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java
index 8a68c5e..aca729e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java
@@ -43,7 +43,7 @@
*/
public class MediaBassBoostTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
private String TAG = "MediaBassBoostTest";
- private final static int MIN_ENERGY_RATIO_2 = 4;
+ private final static int MIN_ENERGY_RATIO_2 = 3;
private final static short TEST_STRENGTH = 500;
private BassBoost mBassBoost = null;
@@ -259,52 +259,6 @@
// private methods
//----------------------------------
- private class EnergyProbe {
- Visualizer mVisualizer = null;
- private byte[] mFft = new byte[1024];
-
- public EnergyProbe(int session) {
- mVisualizer = new Visualizer(session);
- mVisualizer.setCaptureSize(1024);
- }
-
- public int capture(int freq) throws InterruptedException {
- int energy = 0;
- int count = 0;
- if (mVisualizer != null) {
- mVisualizer.setEnabled(true);
- for (int i = 0; i < 10; i++) {
- if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) {
- // TODO: check speex FFT as it seems to return only the number of points
- // correspondong to valid part of the spectrum (< Fs).
- // e.g., if the number of points is 1024, it covers the frequency range
- // 0 to 22050 instead of 0 to 44100 as expected from an FFT.
- int bin = freq / (22050 / 1024);
- int tmp = 0;
- for (int j = bin-2; j < bin+3; j++) {
- tmp += (int)mFft[j] * (int)mFft[j];
- }
- energy += tmp/5;
- count++;
- }
- Thread.sleep(50);
- }
- mVisualizer.setEnabled(false);
- }
- if (count == 0) {
- return 0;
- }
- return energy/count;
- }
-
- public void release() {
- if (mVisualizer != null) {
- mVisualizer.release();
- mVisualizer = null;
- }
- }
- }
-
private void getBassBoost(int session) {
if (mBassBoost == null || session != mSession) {
if (session != mSession && mBassBoost != null) {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
new file mode 100644
index 0000000..db0db70
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2010 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.mediaframeworktest.functional;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaNames;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.AudioEffect;
+import android.media.AudioManager;
+import android.media.EnvironmentalReverb;
+import android.media.Visualizer;
+import android.media.MediaPlayer;
+
+import android.os.Looper;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+/**
+ * Junit / Instrumentation test case for the media AudioTrack api
+
+ */
+public class MediaEnvReverbTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+ private String TAG = "MediaEnvReverbTest";
+ // allow +/- 100 millibel difference between set and get gains
+ private final static int MILLIBEL_TOLERANCE = 100;
+ // allow +/- 5% tolerance between set and get delays
+ private final static float DELAY_TOLERANCE = 1.05f;
+ // allow +/- 5% tolerance between set and get ratios
+ private final static float RATIO_TOLERANCE = 1.05f;
+
+ private EnvironmentalReverb mReverb = null;
+ private int mSession = -1;
+
+ public MediaEnvReverbTest() {
+ super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ releaseReverb();
+ }
+
+ private static void assumeTrue(String message, boolean cond) {
+ assertTrue("(assume)"+message, cond);
+ }
+
+ private void log(String testName, String message) {
+ Log.v(TAG, "["+testName+"] "+message);
+ }
+
+ private void loge(String testName, String message) {
+ Log.e(TAG, "["+testName+"] "+message);
+ }
+
+ //-----------------------------------------------------------------
+ // ENVIRONMENTAL REVEB TESTS:
+ //----------------------------------
+
+
+ //-----------------------------------------------------------------
+ // 0 - constructor
+ //----------------------------------
+
+ //Test case 0.0: test constructor and release
+ @LargeTest
+ public void test0_0ConstructorAndRelease() throws Exception {
+ boolean result = false;
+ String msg = "test1_0ConstructorAndRelease()";
+ EnvironmentalReverb reverb = null;
+ try {
+ reverb = new EnvironmentalReverb(0, 0);
+ assertNotNull(msg + ": could not create EnvironmentalReverb", reverb);
+ try {
+ assertTrue(msg +": invalid effect ID", (reverb.getId() != 0));
+ } catch (IllegalStateException e) {
+ msg = msg.concat(": EnvironmentalReverb not initialized");
+ }
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": EnvironmentalReverb not found");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": Effect library not loaded");
+ } finally {
+ if (reverb != null) {
+ reverb.release();
+ }
+ }
+ assertTrue(msg, result);
+ }
+
+ //-----------------------------------------------------------------
+ // 1 - get/set parameters
+ //----------------------------------
+
+ //Test case 1.0: test room level and room HF level
+ @LargeTest
+ public void test1_0Room() throws Exception {
+ boolean result = false;
+ String msg = "test1_0Room()";
+ getReverb(0);
+ try {
+ mReverb.setRoomLevel((short)0);
+ short level = mReverb.getRoomLevel();
+ assertTrue(msg +": got incorrect room level",
+ (level > (0 - MILLIBEL_TOLERANCE)) &&
+ (level < (0 + MILLIBEL_TOLERANCE)));
+
+ mReverb.setRoomHFLevel((short)-6);
+ level = mReverb.getRoomHFLevel();
+ assertTrue(msg +": got incorrect room HF level",
+ (level > (-6 - MILLIBEL_TOLERANCE)) &&
+ (level < (-6 + MILLIBEL_TOLERANCE)));
+
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": Bad parameter value");
+ loge(msg, "Bad parameter value");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": get parameter() rejected");
+ loge(msg, "get parameter() rejected");
+ } catch (IllegalStateException e) {
+ msg = msg.concat("get parameter() called in wrong state");
+ loge(msg, "get parameter() called in wrong state");
+ } finally {
+ releaseReverb();
+ }
+ assertTrue(msg, result);
+ }
+
+ //Test case 1.1: test decay time and ratio
+ @LargeTest
+ public void test1_1Decay() throws Exception {
+ boolean result = false;
+ String msg = "test1_1Decay()";
+ getReverb(0);
+ try {
+ mReverb.setDecayTime(500);
+ int time = mReverb.getDecayTime();
+ assertTrue(msg +": got incorrect decay time",
+ ((float)time > (float)(500 / DELAY_TOLERANCE)) &&
+ ((float)time < (float)(500 * DELAY_TOLERANCE)));
+
+ mReverb.setDecayHFRatio((short)1000);
+ short ratio = mReverb.getDecayHFRatio();
+ assertTrue(msg +": got incorrect decay HF ratio",
+ ((float)ratio > (float)(1000 / RATIO_TOLERANCE)) &&
+ ((float)ratio < (float)(1000 * RATIO_TOLERANCE)));
+
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": Bad parameter value");
+ loge(msg, "Bad parameter value");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": get parameter() rejected");
+ loge(msg, "get parameter() rejected");
+ } catch (IllegalStateException e) {
+ msg = msg.concat("get parameter() called in wrong state");
+ loge(msg, "get parameter() called in wrong state");
+ } finally {
+ releaseReverb();
+ }
+ assertTrue(msg, result);
+ }
+
+ //Test case 1.2: test reflections
+ @LargeTest
+ public void test1_2Reflections() throws Exception {
+ // TODO: uncomment when early reflections are implemented
+// boolean result = false;
+// String msg = "test1_2Reflections()";
+// getReverb(0);
+// try {
+// mReverb.setReflectionsLevel((short)0);
+// short level = mReverb.getReflectionsLevel();
+// assertTrue(msg +": got incorrect reflections level",
+// (level > (0 - MILLIBEL_TOLERANCE)) &&
+// (level < (0 + MILLIBEL_TOLERANCE)));
+//
+// mReverb.setReflectionsDelay(30);
+// int delay = mReverb.getReflectionsDelay();
+// assertTrue(msg +": got incorrect reflections delay",
+// ((float)delay > (float)(30 / DELAY_TOLERANCE)) &&
+// ((float)delay < (float)(30 * DELAY_TOLERANCE)));
+//
+// result = true;
+// } catch (IllegalArgumentException e) {
+// msg = msg.concat(": Bad parameter value");
+// loge(msg, "Bad parameter value");
+// } catch (UnsupportedOperationException e) {
+// msg = msg.concat(": get parameter() rejected");
+// loge(msg, "get parameter() rejected");
+// } catch (IllegalStateException e) {
+// msg = msg.concat("get parameter() called in wrong state");
+// loge(msg, "get parameter() called in wrong state");
+// } finally {
+// releaseReverb();
+// }
+// assertTrue(msg, result);
+ }
+
+ //Test case 1.3: test reverb
+ @LargeTest
+ public void test1_3Reverb() throws Exception {
+ boolean result = false;
+ String msg = "test1_3Reverb()";
+ getReverb(0);
+ try {
+ mReverb.setReverbLevel((short)0);
+ short level = mReverb.getReverbLevel();
+ assertTrue(msg +": got incorrect reverb level",
+ (level > (0 - MILLIBEL_TOLERANCE)) &&
+ (level < (0 + MILLIBEL_TOLERANCE)));
+
+ // TODO: change delay when early reflections are implemented
+ mReverb.setReverbDelay(0);
+ int delay = mReverb.getReverbDelay();
+ assertTrue(msg +": got incorrect reverb delay", delay < 5);
+
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": Bad parameter value");
+ loge(msg, "Bad parameter value");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": get parameter() rejected");
+ loge(msg, "get parameter() rejected");
+ } catch (IllegalStateException e) {
+ msg = msg.concat("get parameter() called in wrong state");
+ loge(msg, "get parameter() called in wrong state");
+ } finally {
+ releaseReverb();
+ }
+ assertTrue(msg, result);
+ }
+
+ //Test case 1.4: test diffusion and density
+ @LargeTest
+ public void test1_4DiffusionAndDensity() throws Exception {
+ boolean result = false;
+ String msg = "test1_4DiffusionAndDensity()";
+ getReverb(0);
+ try {
+ mReverb.setDiffusion((short)500);
+ short diffusion = mReverb.getDiffusion();
+ assertTrue(msg +": got incorrect diffusion",
+ ((float)diffusion > (float)(500 / RATIO_TOLERANCE)) &&
+ ((float)diffusion < (float)(500 * RATIO_TOLERANCE)));
+
+ mReverb.setDensity((short)500);
+ short density = mReverb.getDensity();
+ assertTrue(msg +": got incorrect density",
+ ((float)density > (float)(500 / RATIO_TOLERANCE)) &&
+ ((float)density < (float)(500 * RATIO_TOLERANCE)));
+
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": Bad parameter value");
+ loge(msg, "Bad parameter value");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": get parameter() rejected");
+ loge(msg, "get parameter() rejected");
+ } catch (IllegalStateException e) {
+ msg = msg.concat("get parameter() called in wrong state");
+ loge(msg, "get parameter() called in wrong state");
+ } finally {
+ releaseReverb();
+ }
+ assertTrue(msg, result);
+ }
+
+ //Test case 1.5: test properties
+ @LargeTest
+ public void test1_5Properties() throws Exception {
+ boolean result = false;
+ String msg = "test1_5Properties()";
+ getReverb(0);
+ try {
+ EnvironmentalReverb.Settings settings = mReverb.getProperties();
+ short newRoomLevel = 0;
+ if (settings.roomLevel == 0) {
+ newRoomLevel = -1000;
+ }
+ String str = settings.toString();
+ settings = new EnvironmentalReverb.Settings(str);
+ settings.roomLevel = newRoomLevel;
+ mReverb.setProperties(settings);
+ settings = mReverb.getProperties();
+ assertTrue(msg +": setProperties failed",
+ (settings.roomLevel > (newRoomLevel - MILLIBEL_TOLERANCE)) &&
+ (settings.roomLevel < (newRoomLevel + MILLIBEL_TOLERANCE)));
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": Bad parameter value");
+ loge(msg, "Bad parameter value");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": get parameter() rejected");
+ loge(msg, "get parameter() rejected");
+ } catch (IllegalStateException e) {
+ msg = msg.concat("get parameter() called in wrong state");
+ loge(msg, "get parameter() called in wrong state");
+ } finally {
+ releaseReverb();
+ }
+ assertTrue(msg, result);
+ }
+
+ //-----------------------------------------------------------------
+ // 2 - Effect action
+ //----------------------------------
+
+ //Test case 2.0: test actual auxiliary reverb influence on sound
+ @LargeTest
+ public void test2_0AuxiliarySoundModification() throws Exception {
+ boolean result = false;
+ String msg = "test2_0AuxiliarySoundModification()";
+ EnergyProbe probe = null;
+ AudioEffect vc = null;
+ MediaPlayer mp = null;
+ AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
+ int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ am.setStreamVolume(AudioManager.STREAM_MUSIC,
+ am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
+ 0);
+ getReverb(0);
+ try {
+ probe = new EnergyProbe(0);
+ // creating a volume controller on output mix ensures that ro.audio.silent mutes
+ // audio after the effects and not before
+ vc = new AudioEffect(
+ AudioEffect.EFFECT_TYPE_NULL,
+ UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
+ 0,
+ 0);
+ vc.setEnabled(true);
+
+ mp = new MediaPlayer();
+ mp.setDataSource(MediaNames.SINE_200_1000);
+ mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+ mp.attachAuxEffect(mReverb.getId());
+ mp.setAuxEffectSendLevel(1.0f);
+ mReverb.setRoomLevel((short)0);
+ mReverb.setReverbLevel((short)0);
+ mReverb.setDecayTime(2000);
+ mReverb.setEnabled(true);
+ mp.prepare();
+ mp.start();
+ Thread.sleep(1000);
+ mp.stop();
+ Thread.sleep(300);
+ // measure energy around 1kHz after media player was stopped for 300 ms
+ int energy1000 = probe.capture(1000);
+ assertTrue(msg + ": reverb has no effect", energy1000 > 0);
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": Bad parameter value");
+ loge(msg, "Bad parameter value");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": get parameter() rejected");
+ loge(msg, "get parameter() rejected");
+ } catch (IllegalStateException e) {
+ msg = msg.concat("get parameter() called in wrong state");
+ loge(msg, "get parameter() called in wrong state");
+ } catch (InterruptedException e) {
+ loge(msg, "sleep() interrupted");
+ }
+ finally {
+ releaseReverb();
+ if (mp != null) {
+ mp.release();
+ }
+ if (vc != null) {
+ vc.release();
+ }
+ if (probe != null) {
+ probe.release();
+ }
+ am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
+ }
+ assertTrue(msg, result);
+ }
+
+ //Test case 2.1: test actual insert reverb influence on sound
+ @LargeTest
+ public void test2_1InsertSoundModification() throws Exception {
+ boolean result = false;
+ String msg = "test2_1InsertSoundModification()";
+ EnergyProbe probe = null;
+ AudioEffect vc = null;
+ MediaPlayer mp = null;
+ AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
+ int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ am.setStreamVolume(AudioManager.STREAM_MUSIC,
+ am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
+ 0);
+ try {
+ probe = new EnergyProbe(0);
+ // creating a volume controller on output mix ensures that ro.audio.silent mutes
+ // audio after the effects and not before
+ vc = new AudioEffect(
+ AudioEffect.EFFECT_TYPE_NULL,
+ UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
+ 0,
+ 0);
+ vc.setEnabled(true);
+
+ mp = new MediaPlayer();
+ mp.setDataSource(MediaNames.SINE_200_1000);
+ mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+ getReverb(mp.getAudioSessionId());
+ mReverb.setRoomLevel((short)0);
+ mReverb.setReverbLevel((short)0);
+ mReverb.setDecayTime(2000);
+ mReverb.setEnabled(true);
+ mp.prepare();
+ mp.start();
+ Thread.sleep(1000);
+ mp.stop();
+ Thread.sleep(300);
+ // measure energy around 1kHz after media player was stopped for 300 ms
+ int energy1000 = probe.capture(1000);
+ assertTrue(msg + ": reverb has no effect", energy1000 > 0);
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": Bad parameter value");
+ loge(msg, "Bad parameter value");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": get parameter() rejected");
+ loge(msg, "get parameter() rejected");
+ } catch (IllegalStateException e) {
+ msg = msg.concat("get parameter() called in wrong state");
+ loge(msg, "get parameter() called in wrong state");
+ } catch (InterruptedException e) {
+ loge(msg, "sleep() interrupted");
+ }
+ finally {
+ releaseReverb();
+ if (mp != null) {
+ mp.release();
+ }
+ if (vc != null) {
+ vc.release();
+ }
+ if (probe != null) {
+ probe.release();
+ }
+ am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
+ }
+ assertTrue(msg, result);
+ }
+
+ //-----------------------------------------------------------------
+ // private methods
+ //----------------------------------
+
+ private void getReverb(int session) {
+ if (mReverb == null || session != mSession) {
+ if (session != mSession && mReverb != null) {
+ mReverb.release();
+ mReverb = null;
+ }
+ try {
+ mReverb = new EnvironmentalReverb(0, session);
+ mSession = session;
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "getReverb() EnvironmentalReverb not found exception: "+e);
+ } catch (UnsupportedOperationException e) {
+ Log.e(TAG, "getReverb() Effect library not loaded exception: "+e);
+ }
+ }
+ assertNotNull("could not create mReverb", mReverb);
+ }
+
+ private void releaseReverb() {
+ if (mReverb != null) {
+ mReverb.release();
+ mReverb = null;
+ }
+ }
+
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java
index e46887b..7b3945d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java
@@ -322,52 +322,6 @@
// private methods
//----------------------------------
- private class EnergyProbe {
- Visualizer mVisualizer = null;
- private byte[] mFft = new byte[1024];
-
- public EnergyProbe(int session) {
- mVisualizer = new Visualizer(session);
- mVisualizer.setCaptureSize(1024);
- }
-
- public int capture(int freq) throws InterruptedException {
- int energy = 0;
- int count = 0;
- if (mVisualizer != null) {
- mVisualizer.setEnabled(true);
- for (int i = 0; i < 10; i++) {
- if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) {
- // TODO: check speex FFT as it seems to return only the number of points
- // correspondong to valid part of the spectrum (< Fs).
- // e.g., if the number of points is 1024, it covers the frequency range
- // 0 to 22050 instead of 0 to 44100 as expected from an FFT.
- int bin = freq / (22050 / 1024);
- int tmp = 0;
- for (int j = bin-2; j < bin+3; j++) {
- tmp += (int)mFft[j] * (int)mFft[j];
- }
- energy += tmp/5;
- count++;
- }
- Thread.sleep(50);
- }
- mVisualizer.setEnabled(false);
- }
- if (count == 0) {
- return 0;
- }
- return energy/count;
- }
-
- public void release() {
- if (mVisualizer != null) {
- mVisualizer.release();
- mVisualizer = null;
- }
- }
- }
-
private void getEqualizer(int session) {
if (mEqualizer == null || session != mSession) {
if (session != mSession && mEqualizer != null) {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
new file mode 100644
index 0000000..c14319a
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2010 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.mediaframeworktest.functional;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaNames;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.AudioEffect;
+import android.media.AudioManager;
+import android.media.PresetReverb;
+import android.media.Visualizer;
+import android.media.MediaPlayer;
+
+import android.os.Looper;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+/**
+ * Junit / Instrumentation test case for the media AudioTrack api
+
+ */
+public class MediaPresetReverbTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+ private String TAG = "MediaPresetReverbTest";
+
+ private PresetReverb mReverb = null;
+ private int mSession = -1;
+
+ public MediaPresetReverbTest() {
+ super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ releaseReverb();
+ }
+
+ private static void assumeTrue(String message, boolean cond) {
+ assertTrue("(assume)"+message, cond);
+ }
+
+ private void log(String testName, String message) {
+ Log.v(TAG, "["+testName+"] "+message);
+ }
+
+ private void loge(String testName, String message) {
+ Log.e(TAG, "["+testName+"] "+message);
+ }
+
+ //-----------------------------------------------------------------
+ // PRESET REVEB TESTS:
+ //----------------------------------
+
+
+ //-----------------------------------------------------------------
+ // 0 - constructor
+ //----------------------------------
+
+ //Test case 0.0: test constructor and release
+ @LargeTest
+ public void test0_0ConstructorAndRelease() throws Exception {
+ boolean result = false;
+ String msg = "test1_0ConstructorAndRelease()";
+ PresetReverb reverb = null;
+ try {
+ reverb = new PresetReverb(0, 0);
+ assertNotNull(msg + ": could not create PresetReverb", reverb);
+ try {
+ assertTrue(msg +": invalid effect ID", (reverb.getId() != 0));
+ } catch (IllegalStateException e) {
+ msg = msg.concat(": PresetReverb not initialized");
+ }
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": PresetReverb not found");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": Effect library not loaded");
+ } finally {
+ if (reverb != null) {
+ reverb.release();
+ }
+ }
+ assertTrue(msg, result);
+ }
+
+ //-----------------------------------------------------------------
+ // 1 - get/set parameters
+ //----------------------------------
+
+ //Test case 1.0: test preset
+ @LargeTest
+ public void test1_0Preset() throws Exception {
+ boolean result = false;
+ String msg = "test1_0Preset()";
+ getReverb(0);
+ try {
+ mReverb.setPreset((short)PresetReverb.PRESET_LARGEROOM);
+ short preset = mReverb.getPreset();
+ assertEquals(msg +": got incorrect preset",
+ (short)PresetReverb.PRESET_LARGEROOM,
+ preset);
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": Bad parameter value");
+ loge(msg, "Bad parameter value");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": get parameter() rejected");
+ loge(msg, "get parameter() rejected");
+ } catch (IllegalStateException e) {
+ msg = msg.concat("get parameter() called in wrong state");
+ loge(msg, "get parameter() called in wrong state");
+ } finally {
+ releaseReverb();
+ }
+ assertTrue(msg, result);
+ }
+
+ //Test case 1.1: test properties
+ @LargeTest
+ public void test1_1Properties() throws Exception {
+ boolean result = false;
+ String msg = "test1_1Properties()";
+ getReverb(0);
+ try {
+ PresetReverb.Settings settings = mReverb.getProperties();
+ short newPreset = (short)PresetReverb.PRESET_LARGEROOM;
+ if (settings.preset == (short)PresetReverb.PRESET_LARGEROOM) {
+ newPreset = (short)PresetReverb.PRESET_SMALLROOM;
+ }
+ String str = settings.toString();
+ settings = new PresetReverb.Settings(str);
+ settings.preset = newPreset;
+ mReverb.setProperties(settings);
+ settings = mReverb.getProperties();
+ assertEquals(msg +": setProperties failed", newPreset, settings.preset);
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": Bad parameter value");
+ loge(msg, "Bad parameter value");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": get parameter() rejected");
+ loge(msg, "get parameter() rejected");
+ } catch (IllegalStateException e) {
+ msg = msg.concat("get parameter() called in wrong state");
+ loge(msg, "get parameter() called in wrong state");
+ } finally {
+ releaseReverb();
+ }
+ assertTrue(msg, result);
+ }
+
+ //-----------------------------------------------------------------
+ // 2 - Effect action
+ //----------------------------------
+
+ //Test case 2.0: test actual auxiliary reverb influence on sound
+ @LargeTest
+ public void test2_0AuxiliarySoundModification() throws Exception {
+ boolean result = false;
+ String msg = "test2_0AuxiliarySoundModification()";
+ EnergyProbe probe = null;
+ AudioEffect vc = null;
+ MediaPlayer mp = null;
+ AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
+ int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ am.setStreamVolume(AudioManager.STREAM_MUSIC,
+ am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
+ 0);
+ getReverb(0);
+ try {
+ probe = new EnergyProbe(0);
+ // creating a volume controller on output mix ensures that ro.audio.silent mutes
+ // audio after the effects and not before
+ vc = new AudioEffect(
+ AudioEffect.EFFECT_TYPE_NULL,
+ UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
+ 0,
+ 0);
+ vc.setEnabled(true);
+
+ mp = new MediaPlayer();
+ mp.setDataSource(MediaNames.SINE_200_1000);
+ mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+ mp.attachAuxEffect(mReverb.getId());
+ mp.setAuxEffectSendLevel(1.0f);
+ mReverb.setPreset((short)PresetReverb.PRESET_PLATE);
+ mReverb.setEnabled(true);
+ mp.prepare();
+ mp.start();
+ Thread.sleep(1000);
+ mp.stop();
+ Thread.sleep(200);
+ // measure energy around 1kHz after media player was stopped for 200 ms
+ int energy1000 = probe.capture(1000);
+ assertTrue(msg + ": reverb has no effect", energy1000 > 0);
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": Bad parameter value");
+ loge(msg, "Bad parameter value");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": get parameter() rejected");
+ loge(msg, "get parameter() rejected");
+ } catch (IllegalStateException e) {
+ msg = msg.concat("get parameter() called in wrong state");
+ loge(msg, "get parameter() called in wrong state");
+ } catch (InterruptedException e) {
+ loge(msg, "sleep() interrupted");
+ }
+ finally {
+ releaseReverb();
+ if (mp != null) {
+ mp.release();
+ }
+ if (vc != null) {
+ vc.release();
+ }
+ if (probe != null) {
+ probe.release();
+ }
+ am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
+ }
+ assertTrue(msg, result);
+ }
+
+ //Test case 2.1: test actual insert reverb influence on sound
+ @LargeTest
+ public void test2_1InsertSoundModification() throws Exception {
+ boolean result = false;
+ String msg = "test2_1InsertSoundModification()";
+ EnergyProbe probe = null;
+ AudioEffect vc = null;
+ MediaPlayer mp = null;
+ AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
+ int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ am.setStreamVolume(AudioManager.STREAM_MUSIC,
+ am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
+ 0);
+ try {
+ probe = new EnergyProbe(0);
+ // creating a volume controller on output mix ensures that ro.audio.silent mutes
+ // audio after the effects and not before
+ vc = new AudioEffect(
+ AudioEffect.EFFECT_TYPE_NULL,
+ UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
+ 0,
+ 0);
+ vc.setEnabled(true);
+
+ mp = new MediaPlayer();
+ mp.setDataSource(MediaNames.SINE_200_1000);
+ mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+ getReverb(mp.getAudioSessionId());
+ mReverb.setPreset((short)PresetReverb.PRESET_PLATE);
+ mReverb.setEnabled(true);
+ mp.prepare();
+ mp.start();
+ Thread.sleep(1000);
+ mp.stop();
+ Thread.sleep(200);
+ // measure energy around 1kHz after media player was stopped for 200 ms
+ int energy1000 = probe.capture(1000);
+ assertTrue(msg + ": reverb has no effect", energy1000 > 0);
+ result = true;
+ } catch (IllegalArgumentException e) {
+ msg = msg.concat(": Bad parameter value");
+ loge(msg, "Bad parameter value");
+ } catch (UnsupportedOperationException e) {
+ msg = msg.concat(": get parameter() rejected");
+ loge(msg, "get parameter() rejected");
+ } catch (IllegalStateException e) {
+ msg = msg.concat("get parameter() called in wrong state");
+ loge(msg, "get parameter() called in wrong state");
+ } catch (InterruptedException e) {
+ loge(msg, "sleep() interrupted");
+ }
+ finally {
+ releaseReverb();
+ if (mp != null) {
+ mp.release();
+ }
+ if (vc != null) {
+ vc.release();
+ }
+ if (probe != null) {
+ probe.release();
+ }
+ am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
+ }
+ assertTrue(msg, result);
+ }
+
+ //-----------------------------------------------------------------
+ // private methods
+ //----------------------------------
+
+ private void getReverb(int session) {
+ if (mReverb == null || session != mSession) {
+ if (session != mSession && mReverb != null) {
+ mReverb.release();
+ mReverb = null;
+ }
+ try {
+ mReverb = new PresetReverb(0, session);
+ mSession = session;
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "getReverb() PresetReverb not found exception: "+e);
+ } catch (UnsupportedOperationException e) {
+ Log.e(TAG, "getReverb() Effect library not loaded exception: "+e);
+ }
+ }
+ assertNotNull("could not create mReverb", mReverb);
+ }
+
+ private void releaseReverb() {
+ if (mReverb != null) {
+ mReverb.release();
+ mReverb = null;
+ }
+ }
+
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java
index 6b8ae44..517d575 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java
@@ -43,7 +43,7 @@
*/
public class MediaVirtualizerTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
private String TAG = "MediaVirtualizerTest";
- private final static int MIN_ENERGY_RATIO_2 = 4;
+ private final static int MIN_ENERGY_RATIO_2 = 3;
private final static short TEST_STRENGTH = 500;
private Virtualizer mVirtualizer = null;
@@ -224,7 +224,7 @@
int energy200 = probe.capture(200);
int energy1000 = probe.capture(1000);
// verify that the energy ration between low and high frequencies is at least
- // four times higher with virtualizer on.
+ // MIN_ENERGY_RATIO_2 times higher with virtualizer on.
// NOTE: this is what is observed with current virtualizer implementation and the test
// audio file but is not the primary effect of the virtualizer. A better way would
// be to have a stereo PCM capture and check that a strongly paned input is centered
@@ -264,52 +264,6 @@
// private methods
//----------------------------------
- private class EnergyProbe {
- Visualizer mVisualizer = null;
- private byte[] mFft = new byte[1024];
-
- public EnergyProbe(int session) {
- mVisualizer = new Visualizer(session);
- mVisualizer.setCaptureSize(1024);
- }
-
- public int capture(int freq) throws InterruptedException {
- int energy = 0;
- int count = 0;
- if (mVisualizer != null) {
- mVisualizer.setEnabled(true);
- for (int i = 0; i < 10; i++) {
- if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) {
- // TODO: check speex FFT as it seems to return only the number of points
- // correspondong to valid part of the spectrum (< Fs).
- // e.g., if the number of points is 1024, it covers the frequency range
- // 0 to 22050 instead of 0 to 44100 as expected from an FFT.
- int bin = freq / (22050 / 1024);
- int tmp = 0;
- for (int j = bin-2; j < bin+3; j++) {
- tmp += (int)mFft[j] * (int)mFft[j];
- }
- energy += tmp/5;
- count++;
- }
- Thread.sleep(50);
- }
- mVisualizer.setEnabled(false);
- }
- if (count == 0) {
- return 0;
- }
- return energy/count;
- }
-
- public void release() {
- if (mVisualizer != null) {
- mVisualizer.release();
- mVisualizer = null;
- }
- }
- }
-
private void getVirtualizer(int session) {
if (mVirtualizer == null || session != mSession) {
if (session != mSession && mVirtualizer != null) {
diff --git a/opengl/java/android/opengl/GLWallpaperService.java b/opengl/java/android/opengl/GLWallpaperService.java
new file mode 100644
index 0000000..c954fed
--- /dev/null
+++ b/opengl/java/android/opengl/GLWallpaperService.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.opengl;
+
+/**
+ * reserve this namespace for future use
+ * (making sure external developers don't use it)
+ * @hide
+ */
+class GLWallpaperService {
+}
diff --git a/packages/SystemUI/res/drawable-hdpi/notification_dragger.png b/packages/SystemUI/res/drawable-hdpi/notification_dragger.png
deleted file mode 100644
index 71b5507..0000000
--- a/packages/SystemUI/res/drawable-hdpi/notification_dragger.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_0.png b/packages/SystemUI/res/drawable-mdpi/battery_0.png
index 77162c8..e81638d 100644
--- a/packages/SystemUI/res/drawable-mdpi/battery_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_10.png b/packages/SystemUI/res/drawable-mdpi/battery_10.png
new file mode 100644
index 0000000..a739f50
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/battery_10.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_100.png b/packages/SystemUI/res/drawable-mdpi/battery_100.png
index 588a74b..9a66db38 100644
--- a/packages/SystemUI/res/drawable-mdpi/battery_100.png
+++ b/packages/SystemUI/res/drawable-mdpi/battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_25.png b/packages/SystemUI/res/drawable-mdpi/battery_25.png
index b11570b..7ae7ebb 100644
--- a/packages/SystemUI/res/drawable-mdpi/battery_25.png
+++ b/packages/SystemUI/res/drawable-mdpi/battery_25.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_5.png b/packages/SystemUI/res/drawable-mdpi/battery_5.png
new file mode 100644
index 0000000..1a15a21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/battery_5.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_50.png b/packages/SystemUI/res/drawable-mdpi/battery_50.png
index 94d7eca..7088066 100644
--- a/packages/SystemUI/res/drawable-mdpi/battery_50.png
+++ b/packages/SystemUI/res/drawable-mdpi/battery_50.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_75.png b/packages/SystemUI/res/drawable-mdpi/battery_75.png
index 3cb3591..d4cfb6f 100644
--- a/packages/SystemUI/res/drawable-mdpi/battery_75.png
+++ b/packages/SystemUI/res/drawable-mdpi/battery_75.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notification_dragger.png b/packages/SystemUI/res/drawable-mdpi/notification_dragger.png
deleted file mode 100644
index fad1f32..0000000
--- a/packages/SystemUI/res/drawable-mdpi/notification_dragger.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_0.png b/packages/SystemUI/res/drawable-mdpi/signal_0.png
index cf436ad..ff2727b 100644
--- a/packages/SystemUI/res/drawable-mdpi/signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_100.png b/packages/SystemUI/res/drawable-mdpi/signal_100.png
index 0011a1b..55c34ff 100644
--- a/packages/SystemUI/res/drawable-mdpi/signal_100.png
+++ b/packages/SystemUI/res/drawable-mdpi/signal_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_25.png b/packages/SystemUI/res/drawable-mdpi/signal_25.png
index 69c643f..a415596 100644
--- a/packages/SystemUI/res/drawable-mdpi/signal_25.png
+++ b/packages/SystemUI/res/drawable-mdpi/signal_25.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_50.png b/packages/SystemUI/res/drawable-mdpi/signal_50.png
index c8acd72..3c5a708b0 100644
--- a/packages/SystemUI/res/drawable-mdpi/signal_50.png
+++ b/packages/SystemUI/res/drawable-mdpi/signal_50.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_75.png b/packages/SystemUI/res/drawable-mdpi/signal_75.png
index 9650dfa..e176f37 100644
--- a/packages/SystemUI/res/drawable-mdpi/signal_75.png
+++ b/packages/SystemUI/res/drawable-mdpi/signal_75.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_scan1.png b/packages/SystemUI/res/drawable-mdpi/signal_scan1.png
new file mode 100644
index 0000000..f64b9cc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/signal_scan1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_scan2.png b/packages/SystemUI/res/drawable-mdpi/signal_scan2.png
new file mode 100644
index 0000000..982feb4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/signal_scan2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_scan3.png b/packages/SystemUI/res/drawable-mdpi/signal_scan3.png
new file mode 100644
index 0000000..a4c0689
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/signal_scan3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_scan4.png b/packages/SystemUI/res/drawable-mdpi/signal_scan4.png
new file mode 100644
index 0000000..d1e95fe
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/signal_scan4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.png
index 5c57802..a2527b3 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
index b2a94b6..ce64926 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
index b2a94b6..c63c426 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.png
index f219ded..9e64fe8 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.png
index 4dd8dc7..350a3e9 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/wifi_0.png b/packages/SystemUI/res/drawable-mdpi/wifi_0.png
new file mode 100644
index 0000000..e81638d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/wifi_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/wifi_100.png b/packages/SystemUI/res/drawable-mdpi/wifi_100.png
new file mode 100644
index 0000000..4468389
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/wifi_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/wifi_25.png b/packages/SystemUI/res/drawable-mdpi/wifi_25.png
new file mode 100644
index 0000000..0e389a7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/wifi_25.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/wifi_50.png b/packages/SystemUI/res/drawable-mdpi/wifi_50.png
new file mode 100644
index 0000000..1cad0d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/wifi_50.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/wifi_75.png b/packages/SystemUI/res/drawable-mdpi/wifi_75.png
new file mode 100644
index 0000000..dd2d7dc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/wifi_75.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/wifi_scan1.png b/packages/SystemUI/res/drawable-mdpi/wifi_scan1.png
new file mode 100644
index 0000000..0e389a7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/wifi_scan1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/wifi_scan2.png b/packages/SystemUI/res/drawable-mdpi/wifi_scan2.png
new file mode 100644
index 0000000..34e7c70
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/wifi_scan2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/wifi_scan3.png b/packages/SystemUI/res/drawable-mdpi/wifi_scan3.png
new file mode 100644
index 0000000..4c2a9e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/wifi_scan3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/wifi_scan4.png b/packages/SystemUI/res/drawable-mdpi/wifi_scan4.png
new file mode 100644
index 0000000..b504131
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/wifi_scan4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/battery.xml b/packages/SystemUI/res/drawable/battery.xml
index f4a720d..3bc0c74 100644
--- a/packages/SystemUI/res/drawable/battery.xml
+++ b/packages/SystemUI/res/drawable/battery.xml
@@ -20,12 +20,8 @@
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:maxLevel="1" android:drawable="@drawable/battery_0" />
- <item android:maxLevel="5">
- <animation-list android:oneshot="false">
- <item android:drawable="@drawable/battery_0" android:duration="250" />
- <item android:drawable="@drawable/battery_25" android:duration="250" />
- </animation-list>
- </item>
+ <item android:maxLevel="5" android:drawable="@drawable/battery_5" />
+ <item android:maxLevel="10" android:drawable="@drawable/battery_10" />
<item android:maxLevel="25" android:drawable="@drawable/battery_25" />
<item android:maxLevel="50" android:drawable="@drawable/battery_50" />
<item android:maxLevel="75" android:drawable="@drawable/battery_75" />
diff --git a/packages/SystemUI/res/drawable/signal.xml b/packages/SystemUI/res/drawable/signal.xml
index 5aa211a..7367418 100644
--- a/packages/SystemUI/res/drawable/signal.xml
+++ b/packages/SystemUI/res/drawable/signal.xml
@@ -24,6 +24,5 @@
<item android:maxLevel="50" android:drawable="@drawable/signal_50" />
<item android:maxLevel="75" android:drawable="@drawable/signal_75" />
<item android:maxLevel="101" android:drawable="@drawable/signal_100" />
-
</level-list>
diff --git a/packages/SystemUI/res/drawable/signal_scan.xml b/packages/SystemUI/res/drawable/signal_scan.xml
new file mode 100644
index 0000000..fe21992
--- /dev/null
+++ b/packages/SystemUI/res/drawable/signal_scan.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/drawable/stat_sys_battery.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/signal_scan1" android:duration="500" />
+ <item android:drawable="@drawable/signal_scan2" android:duration="500" />
+ <item android:drawable="@drawable/signal_scan3" android:duration="500" />
+ <item android:drawable="@drawable/signal_scan4" android:duration="500" />
+ <item android:drawable="@drawable/signal_scan3" android:duration="500" />
+ <item android:drawable="@drawable/signal_scan2" android:duration="500" />
+</animation-list>
+
diff --git a/packages/SystemUI/res/drawable/wifi.xml b/packages/SystemUI/res/drawable/wifi.xml
new file mode 100644
index 0000000..6e63af6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/wifi.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/drawable/stat_sys_battery.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<level-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:maxLevel="01" android:drawable="@drawable/wifi_0" />
+ <item android:maxLevel="25" android:drawable="@drawable/wifi_25" />
+ <item android:maxLevel="50" android:drawable="@drawable/wifi_50" />
+ <item android:maxLevel="75" android:drawable="@drawable/wifi_75" />
+ <item android:maxLevel="101" android:drawable="@drawable/wifi_100" />
+
+</level-list>
+
diff --git a/packages/SystemUI/res/drawable/wifi_scan.xml b/packages/SystemUI/res/drawable/wifi_scan.xml
new file mode 100644
index 0000000..5888d0e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/wifi_scan.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/drawable/stat_sys_battery.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/wifi_scan1" android:duration="500" />
+ <item android:drawable="@drawable/wifi_scan2" android:duration="500" />
+ <item android:drawable="@drawable/wifi_scan3" android:duration="500" />
+ <item android:drawable="@drawable/wifi_scan4" android:duration="500" />
+ <item android:drawable="@drawable/wifi_scan3" android:duration="500" />
+ <item android:drawable="@drawable/wifi_scan2" android:duration="500" />
+</animation-list>
+
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml
index ffb1571..481bcde 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml
@@ -101,8 +101,8 @@
</LinearLayout>
<include layout="@layout/status_bar_center"
- android:layout_width="100dip"
- android:layout_height="wrap_content"
+ android:layout_width="160dip"
+ android:layout_height="match_parent"
android:layout_centerInParent="true"
/>
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_center.xml b/packages/SystemUI/res/layout-xlarge/status_bar_center.xml
index 775fea0..5bf8316 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_center.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_center.xml
@@ -18,8 +18,8 @@
<RelativeLayout android:id="@+id/systemInfo"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
- android:layout_width="100dip"
- android:layout_height="wrap_content"
+ android:layout_width="160dip"
+ android:layout_height="match_parent"
android:layout_centerInParent="true"
android:clickable="true"
android:onClick="systemInfoClicked"
@@ -27,8 +27,9 @@
<com.android.systemui.statusbar.Clock
style="@*android:style/TextAppearance.StatusBar.Icon"
android:id="@+id/clock"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_width="64dip"
+ android:layout_height="48dip"
+ android:layout_centerInParent="true"
android:singleLine="true"
android:gravity="center"
android:textSize="16sp"
@@ -37,18 +38,16 @@
/>
<ImageView
android:id="@+id/battery"
- android:layout_width="50dip"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_below="@id/clock"
+ android:layout_width="48dip"
+ android:layout_height="48dip"
+ android:layout_toLeftOf="@id/clock"
android:src="@drawable/battery"
/>
<ImageView
android:id="@+id/signal"
- android:layout_width="50dip"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_below="@id/clock"
+ android:layout_width="48dip"
+ android:layout_height="48dip"
+ android:layout_toRightOf="@id/clock"
android:src="@drawable/signal"
/>
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout-xlarge/sysbar_panel_system.xml b/packages/SystemUI/res/layout-xlarge/sysbar_panel_system.xml
index 273674f..36c6388 100644
--- a/packages/SystemUI/res/layout-xlarge/sysbar_panel_system.xml
+++ b/packages/SystemUI/res/layout-xlarge/sysbar_panel_system.xml
@@ -92,8 +92,10 @@
android:layout_alignParentLeft="true"
>
<ImageView android:id="@+id/battery_meter"
- android:layout_width="wrap_content"
+ android:layout_width="96dip"
android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:scaleType="centerCrop"
android:src="@drawable/battery"
/>
@@ -129,8 +131,10 @@
android:layout_alignParentRight="true"
>
<ImageView android:id="@+id/signal_meter"
- android:layout_width="wrap_content"
+ android:layout_width="96dip"
android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:scaleType="centerCrop"
android:src="@drawable/signal"
/>
diff --git a/packages/SystemUI/res/values-xlarge/strings.xml b/packages/SystemUI/res/values-xlarge/strings.xml
index 4aa4b47..3c59c92 100644
--- a/packages/SystemUI/res/values-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-xlarge/strings.xml
@@ -20,4 +20,58 @@
<!-- The text for the button in the notification window-shade that clears
all of the currently visible notifications. -->
<string name="status_bar_clear_all_button">Clear all</string>
+
+ <!-- System panel ("Quick Settings") -->
+
+ <!-- Text to display underneath the graphical battery meter. Should
+ include the word for "battery" and a place for the percentage charge
+ available. [CHAR LIMIT=20] -->
+ <string name="system_panel_battery_meter_format">
+ Battery: <xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g>
+ </string>
+
+ <!-- Text to display underneath the graphical signal strength meter when
+ no connection is available. [CHAR LIMIT=20] -->
+ <string name="system_panel_signal_meter_disconnected">
+ no internet connection
+ </string>
+
+ <!-- Text to display underneath the graphical signal strength meter when
+ it is displaying information about a connected, named Wi-Fi network.
+ Should include the word for "Wi-Fi" and a placeholder for the
+ wireless network's SSID. [CHAR LIMIT=20] -->
+ <string name="system_panel_signal_meter_wifi_ssid_format">
+ Wi-Fi: <xliff:g id="ssid">%s</xliff:g>
+ </string>
+
+ <!-- Text to display underneath the graphical signal strength meter when
+ it is displaying Wi-Fi status and Wi-Fi is connected to a network
+ whose SSID is not available.
+ [CHAR LIMIT=20] -->
+ <string name="system_panel_signal_meter_wifi_nossid">
+ Wi-Fi: connected
+ </string>
+
+ <!-- Text to display underneath the graphical signal strength meter when
+ it is displaying Wi-Fi status and Wi-Fi is in the process of
+ connecting to a network. [CHAR LIMIT=20] -->
+ <string name="system_panel_signal_meter_wifi_connecting">
+ Wi-Fi: connecting…
+ </string>
+
+ <!-- Text to display underneath the graphical signal strength meter when
+ it is displaying mobile data (3G) status and a network connection is
+ available.
+ [CHAR LIMIT=20] -->
+ <string name="system_panel_signal_meter_data_connected">
+ Mobile data: connected
+ </string>
+
+ <!-- Text to display underneath the graphical signal strength meter when
+ it is displaying mobile data (3G) status and a network connection is
+ unavailable.
+ [CHAR LIMIT=20] -->
+ <string name="system_panel_signal_meter_data_connecting">
+ Mobile data: connecting…
+ </string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SystemPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SystemPanel.java
index a03393b..dfa2d10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SystemPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SystemPanel.java
@@ -45,6 +45,7 @@
import android.provider.Settings;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.util.AttributeSet;
import android.util.Slog;
@@ -66,11 +67,18 @@
import java.util.List;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.cdma.EriInfo;
+import com.android.internal.telephony.cdma.TtyIntent;
+
import com.android.systemui.statusbar.*;
import com.android.systemui.R;
public class SystemPanel extends LinearLayout {
private static final String TAG = "SystemPanel";
+ private static final boolean DEBUG = TabletStatusBarService.DEBUG;
+ private static final boolean DEBUG_SIGNAL = true;
private static final int MINIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_DIM + 5;
private static final int MAXIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_ON;
@@ -93,7 +101,22 @@
private final AudioManager mAudioManager;
private final WifiManager mWifiManager;
+ private final TelephonyManager mPhone;
+ // state trackers for telephony code
+ IccCard.State mSimState = IccCard.State.READY;
+ int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
+ int mDataState = TelephonyManager.DATA_DISCONNECTED;
+ ServiceState mServiceState;
+ SignalStrength mSignalStrength;
+
+ // state for the meters
+ boolean mWifiEnabled, mWifiConnected;
+ int mWifiLevel;
+ String mWifiSsid;
+
+ boolean mDataEnabled, mDataConnected, mDataRoaming;
+ int mDataLevel;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
@@ -107,18 +130,154 @@
|| action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)
|| action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)
|| action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- updateWifi(intent);
+ updateWifiState(intent);
+ } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
+ updateSimState(intent);
}
}
};
- boolean mWifiEnabled, mWifiConnected;
- int mWifiLevel;
- String mWifiSsid;
+ private final void updateSimState(Intent intent) {
+ String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
+ if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+ mSimState = IccCard.State.ABSENT;
+ }
+ else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+ mSimState = IccCard.State.READY;
+ }
+ else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+ final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
+ if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+ mSimState = IccCard.State.PIN_REQUIRED;
+ }
+ else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+ mSimState = IccCard.State.PUK_REQUIRED;
+ }
+ else {
+ mSimState = IccCard.State.NETWORK_LOCKED;
+ }
+ } else {
+ mSimState = IccCard.State.UNKNOWN;
+ }
+ updateDataState();
+ }
- private void updateWifi(Intent intent) {
- if (TabletStatusBarService.DEBUG)
- Slog.d(TabletStatusBarService.TAG, "updateWifi: " + intent);
+ private boolean isCdma() {
+ return (mSignalStrength != null) && !mSignalStrength.isGsm();
+ }
+
+ private boolean isEvdo() {
+ return ( (mServiceState != null)
+ && ((mServiceState.getRadioTechnology()
+ == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
+ || (mServiceState.getRadioTechnology()
+ == ServiceState.RADIO_TECHNOLOGY_EVDO_A)
+ || (mServiceState.getRadioTechnology()
+ == ServiceState.RADIO_TECHNOLOGY_EVDO_B)));
+ }
+
+ private boolean hasService() {
+ if (mServiceState != null) {
+ switch (mServiceState.getState()) {
+ case ServiceState.STATE_OUT_OF_SERVICE:
+ case ServiceState.STATE_POWER_OFF:
+ return false;
+ default:
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ private int getCdmaLevel() {
+ if (mSignalStrength == null) return 0;
+ final int cdmaDbm = mSignalStrength.getCdmaDbm();
+ final int cdmaEcio = mSignalStrength.getCdmaEcio();
+ int levelDbm = 0;
+ int levelEcio = 0;
+
+ if (cdmaDbm >= -75) levelDbm = 4;
+ else if (cdmaDbm >= -85) levelDbm = 3;
+ else if (cdmaDbm >= -95) levelDbm = 2;
+ else if (cdmaDbm >= -100) levelDbm = 1;
+ else levelDbm = 0;
+
+ // Ec/Io are in dB*10
+ if (cdmaEcio >= -90) levelEcio = 4;
+ else if (cdmaEcio >= -110) levelEcio = 3;
+ else if (cdmaEcio >= -130) levelEcio = 2;
+ else if (cdmaEcio >= -150) levelEcio = 1;
+ else levelEcio = 0;
+
+ return (levelDbm < levelEcio) ? levelDbm : levelEcio;
+ }
+
+ private int getEvdoLevel() {
+ if (mSignalStrength == null) return 0;
+ int evdoDbm = mSignalStrength.getEvdoDbm();
+ int evdoSnr = mSignalStrength.getEvdoSnr();
+ int levelEvdoDbm = 0;
+ int levelEvdoSnr = 0;
+
+ if (evdoDbm >= -65) levelEvdoDbm = 4;
+ else if (evdoDbm >= -75) levelEvdoDbm = 3;
+ else if (evdoDbm >= -90) levelEvdoDbm = 2;
+ else if (evdoDbm >= -105) levelEvdoDbm = 1;
+ else levelEvdoDbm = 0;
+
+ if (evdoSnr >= 7) levelEvdoSnr = 4;
+ else if (evdoSnr >= 5) levelEvdoSnr = 3;
+ else if (evdoSnr >= 3) levelEvdoSnr = 2;
+ else if (evdoSnr >= 1) levelEvdoSnr = 1;
+ else levelEvdoSnr = 0;
+
+ return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
+ }
+
+ private void updateDataState() {
+ mDataConnected = hasService() && (mDataState == TelephonyManager.DATA_CONNECTED);
+
+ if (isCdma()) {
+ // these functions return a value from 0 to 4, inclusive
+ if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){
+ mDataLevel = getEvdoLevel() * 25;
+ } else {
+ mDataLevel = getCdmaLevel() * 25;
+ }
+ } else {
+ // GSM
+
+ int asu = (mSignalStrength == null) ? 0 : mSignalStrength.getGsmSignalStrength();
+
+ // asu on [0,31]; 99 = unknown
+ // Android has historically shown anything >=12 as "full"
+ // XXX: tune this based on Industry Best Practices(TM)
+ if (asu <= 2 || asu == 99) mDataLevel = 0;
+ else mDataLevel = (int)(((float)Math.max(asu, 15) / 15) * 100);
+
+ mDataRoaming = mPhone.isNetworkRoaming();
+
+ mDataConnected = mDataConnected
+ && (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN);
+ }
+
+ if (DEBUG_SIGNAL || DEBUG) {
+ Slog.d(TAG, "updateDataState: connected=" + mDataConnected
+ + " level=" + mDataLevel
+ + " isEvdo=" + isEvdo()
+ + " isCdma=" + isCdma()
+ + " mPhoneState=" + mPhoneState
+ + " mDataState=" + mDataState
+ );
+ }
+
+ refreshSignalMeters();
+ }
+
+ private void updateWifiState(Intent intent) {
+ if (DEBUG)
+ Slog.d(TAG, "updateWifiState: " + intent);
final String action = intent.getAction();
final boolean wasConnected = mWifiConnected;
@@ -142,8 +301,8 @@
if (mWifiConnected && !wasConnected) {
WifiInfo info = mWifiManager.getConnectionInfo();
- if (TabletStatusBarService.DEBUG)
- Slog.d(TabletStatusBarService.TAG, "updateWifi: just connected: info=" + info);
+ if (DEBUG)
+ Slog.d(TAG, "updateWifiState: just connected: info=" + info);
if (info != null) {
// grab the initial signal strength
@@ -164,22 +323,40 @@
}
}
- if (!mWifiEnabled) {
- mWifiSsid = "disabled";
- mWifiLevel = 0;
- } else if (!mWifiConnected) {
- mWifiSsid = "disconnected";
- mWifiLevel = 0;
- } else if (mWifiSsid == null) {
- mWifiSsid = "unknown";
+ refreshSignalMeters();
+ }
+
+ // figure out what to show: first wifi, then 3G, then nothing
+ void refreshSignalMeters() {
+ if (mSignalMeter == null) return; // no UI yet
+
+ Context ctxt = getContext();
+
+ String text = null;
+ int level = 0;
+
+ if (mWifiConnected) {
+ if (mWifiSsid == null) {
+ text = ctxt.getString(R.string.system_panel_signal_meter_wifi_nossid);
+ } else {
+ text = ctxt.getString(R.string.system_panel_signal_meter_wifi_ssid_format,
+ mWifiSsid);
+ }
+ level = mWifiLevel;
+ } else if (mDataConnected) {
+ text = ctxt.getString(R.string.system_panel_signal_meter_data_connected);
+ level = mDataLevel;
+ } else {
+ text = ctxt.getString(R.string.system_panel_signal_meter_disconnected);
+ level = 0;
}
- mSignalMeter.setImageResource(R.drawable.signal);
- mSignalMeter.setImageLevel(mWifiLevel);
- mSignalText.setText(String.format("Wi-Fi: %s", mWifiSsid)); // XXX: localize
+ mSignalMeter.setImageResource(mWifiConnected ? R.drawable.wifi : R.drawable.signal);
+ mSignalMeter.setImageLevel(level);
+ mSignalText.setText(text);
// hack for now
- mBar.setWifiMeter(mWifiLevel);
+ mBar.setSignalMeter(level, mWifiConnected);
}
public void setBar(TabletStatusBarService bar) {
@@ -192,7 +369,8 @@
mBatteryMeter.setImageResource(plugged ? R.drawable.battery_charging : R.drawable.battery);
mBatteryMeter.setImageLevel(level);
- mBatteryText.setText(String.format("Battery: %d%%", level));
+ mBatteryText.setText(getContext()
+ .getString(R.string.system_panel_battery_meter_format, level));
// hack for now
mBar.setBatteryMeter(level, plugged);
@@ -208,13 +386,21 @@
// get notified of phone state changes
TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
+ telephonyManager.listen(mPhoneStateListener,
+ PhoneStateListener.LISTEN_SERVICE_STATE
+ | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
+ | PhoneStateListener.LISTEN_CALL_STATE
+ | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+ | PhoneStateListener.LISTEN_DATA_ACTIVITY);
// wifi status info
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
- // audio status notifications
+ // audio status
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+
+ // mobile data
+ mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
}
public void onAttachedToWindow() {
@@ -259,6 +445,7 @@
}
});
+ // register for broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
@@ -266,8 +453,9 @@
filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
+ filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
getContext().registerReceiver(mReceiver, filter);
-
+
mBatteryMeter = (ImageView)findViewById(R.id.battery_meter);
mBatteryMeter.setImageResource(R.drawable.battery);
mBatteryMeter.setImageLevel(0);
@@ -277,6 +465,8 @@
mBatteryText = (TextView)findViewById(R.id.battery_info);
mSignalText = (TextView)findViewById(R.id.signal_info);
+
+ refreshSignalMeters();
}
public void onDetachedFromWindow() {
@@ -362,11 +552,42 @@
PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
public void onServiceStateChanged(ServiceState serviceState) {
- Slog.d(TAG, "phone service state changed: " + serviceState.getState());
+ if (DEBUG_SIGNAL || DEBUG) {
+ Slog.d(TAG, "phone service state changed: " + serviceState.getState());
+ }
+ mServiceState = serviceState;
mAirplaneMode = serviceState.getState() == ServiceState.STATE_POWER_OFF;
if (mAirplaneButton != null) {
mAirplaneButton.setAlpha(mAirplaneMode ? 0xFF : 0x7F);
}
+ updateDataState();
+ }
+ @Override
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ if (DEBUG_SIGNAL || DEBUG) {
+ Slog.d(TAG, "onSignalStrengthsChanged: " + signalStrength);
+ }
+ mSignalStrength = signalStrength;
+ updateDataState();
+ }
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ mPhoneState = state;
+ // In cdma, if a voice call is made, RSSI should switch to 1x.
+ if (isCdma()) {
+ updateDataState();
+ }
+ }
+
+ @Override
+ public void onDataConnectionStateChanged(int state, int networkType) {
+ if (DEBUG_SIGNAL || DEBUG) {
+ Slog.d(TAG, "onDataConnectionStateChanged: state=" + state
+ + " type=" + networkType);
+ }
+ mDataState = state;
+// updateDataNetType(networkType);
+ updateDataState();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
index 18b9b41..087671a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
@@ -212,10 +212,15 @@
mBatteryMeter.setImageLevel(level);
}
- public void setWifiMeter(int level) {
- if (DEBUG) Slog.d(TAG, "wifi=" + level);
- mSignalMeter.setImageResource(R.drawable.signal);
- mSignalMeter.setImageLevel(level);
+ public void setSignalMeter(int level, boolean isWifi) {
+ if (DEBUG) Slog.d(TAG, "signal=" + level);
+ if (level < 0) {
+ mSignalMeter.setImageResource(isWifi ? R.drawable.wifi_scan : R.drawable.signal_scan);
+ mSignalMeter.setImageLevel(0);
+ } else {
+ mSignalMeter.setImageResource(isWifi ? R.drawable.wifi : R.drawable.signal);
+ mSignalMeter.setImageLevel(level);
+ }
}
public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index d5750c6..4407e96 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -4798,6 +4798,8 @@
Parcel data = null;
Parcel reply = null;
+ BufferedWriter out = null;
+
// Any uncaught exception will crash the system process
try {
// Find the hashcode of the window
@@ -4835,6 +4837,12 @@
reply.readException();
+ if (!client.isOutputShutdown()) {
+ out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
+ out.write("DONE\n");
+ out.flush();
+ }
+
} catch (Exception e) {
Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
success = false;
@@ -4845,6 +4853,13 @@
if (reply != null) {
reply.recycle();
}
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+
+ }
+ }
}
return success;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 56159b5..123dc3e 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -610,8 +610,8 @@
* All currently bound service connections. Keys are the IBinder of
* the client's IServiceConnection.
*/
- final HashMap<IBinder, ConnectionRecord> mServiceConnections
- = new HashMap<IBinder, ConnectionRecord>();
+ final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
+ = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
/**
* List of services that we have been asked to start,
@@ -4301,12 +4301,10 @@
+ " when granting permission to uri " + uri);
}
if (targetPkg == null) {
- Slog.w(TAG, "grantUriPermission: null target");
- return;
+ throw new IllegalArgumentException("null target");
}
if (uri == null) {
- Slog.w(TAG, "grantUriPermission: null uri");
- return;
+ throw new IllegalArgumentException("null uri");
}
grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
@@ -4458,6 +4456,56 @@
}
}
+ @Override
+ public IBinder newUriPermissionOwner(String name) {
+ synchronized(this) {
+ UriPermissionOwner owner = new UriPermissionOwner(this, name);
+ return owner.getExternalTokenLocked();
+ }
+ }
+
+ @Override
+ public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
+ Uri uri, int modeFlags) {
+ synchronized(this) {
+ UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
+ if (owner == null) {
+ throw new IllegalArgumentException("Unknown owner: " + token);
+ }
+ if (fromUid != Binder.getCallingUid()) {
+ if (Binder.getCallingUid() != Process.myUid()) {
+ // Only system code can grant URI permissions on behalf
+ // of other users.
+ throw new SecurityException("nice try");
+ }
+ }
+ if (targetPkg == null) {
+ throw new IllegalArgumentException("null target");
+ }
+ if (uri == null) {
+ throw new IllegalArgumentException("null uri");
+ }
+
+ grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
+ }
+ }
+
+ @Override
+ public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
+ synchronized(this) {
+ UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
+ if (owner == null) {
+ throw new IllegalArgumentException("Unknown owner: " + token);
+ }
+
+ if (uri == null) {
+ owner.removeUriPermissionsLocked(mode);
+ } else {
+ owner.removeUriPermissionLocked(uri, mode);
+ }
+ }
+ }
+
public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
synchronized (this) {
ProcessRecord app =
@@ -7404,12 +7452,14 @@
if (mServiceConnections.size() > 0) {
if (needSep) pw.println(" ");
pw.println(" Connection bindings to services:");
- Iterator<ConnectionRecord> it
+ Iterator<ArrayList<ConnectionRecord>> it
= mServiceConnections.values().iterator();
while (it.hasNext()) {
- ConnectionRecord r = it.next();
- pw.print(" * "); pw.println(r);
- r.dump(pw, " ");
+ ArrayList<ConnectionRecord> r = it.next();
+ for (int i=0; i<r.size(); i++) {
+ pw.print(" * "); pw.println(r.get(i));
+ r.get(i).dump(pw, " ");
+ }
}
needSep = true;
}
@@ -7687,18 +7737,21 @@
while (it.hasNext()) {
ServiceRecord r = it.next();
if (r.connections.size() > 0) {
- Iterator<ConnectionRecord> jt
+ Iterator<ArrayList<ConnectionRecord>> jt
= r.connections.values().iterator();
while (jt.hasNext()) {
- ConnectionRecord c = jt.next();
- if (c.binding.client != app) {
- try {
- //c.conn.connected(r.className, null);
- } catch (Exception e) {
- // todo: this should be asynchronous!
- Slog.w(TAG, "Exception thrown disconnected servce "
- + r.shortName
- + " from app " + app.processName, e);
+ ArrayList<ConnectionRecord> cl = jt.next();
+ for (int i=0; i<cl.size(); i++) {
+ ConnectionRecord c = cl.get(i);
+ if (c.binding.client != app) {
+ try {
+ //c.conn.connected(r.className, null);
+ } catch (Exception e) {
+ // todo: this should be asynchronous!
+ Slog.w(TAG, "Exception thrown disconnected servce "
+ + r.shortName
+ + " from app " + app.processName, e);
+ }
}
}
}
@@ -7728,7 +7781,9 @@
}
sr.app = null;
sr.executeNesting = 0;
- mStoppingServices.remove(sr);
+ if (mStoppingServices.remove(sr)) {
+ if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
+ }
boolean hasClients = sr.bindings.size() > 0;
if (hasClients) {
@@ -7781,6 +7836,7 @@
ServiceRecord sr = mStoppingServices.get(i);
if (sr.app == app) {
mStoppingServices.remove(i);
+ if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
}
}
@@ -8044,11 +8100,15 @@
if (r.app != null && r.app.persistent) {
info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
}
- for (ConnectionRecord conn : r.connections.values()) {
- if (conn.clientLabel != 0) {
- info.clientPackage = conn.binding.client.info.packageName;
- info.clientLabel = conn.clientLabel;
- break;
+
+ for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
+ for (int i=0; i<connl.size(); i++) {
+ ConnectionRecord conn = connl.get(i);
+ if (conn.clientLabel != 0) {
+ info.clientPackage = conn.binding.client.info.packageName;
+ info.clientLabel = conn.clientLabel;
+ return info;
+ }
}
}
return info;
@@ -8083,9 +8143,11 @@
synchronized (this) {
ServiceRecord r = mServices.get(name);
if (r != null) {
- for (ConnectionRecord conn : r.connections.values()) {
- if (conn.clientIntent != null) {
- return conn.clientIntent;
+ for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
+ for (int i=0; i<conn.size(); i++) {
+ if (conn.get(i).clientIntent != null) {
+ return conn.get(i).clientIntent;
+ }
}
}
}
@@ -8262,8 +8324,8 @@
while (r.pendingStarts.size() > 0) {
try {
ServiceRecord.StartItem si = r.pendingStarts.remove(0);
- if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
- + r.name + " " + r.intent + " args=" + si.intent);
+ if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
+ + r + " " + r.intent + " args=" + si.intent);
if (si.intent == null) {
// If somehow we got a dummy start at the front, then
// just drop it here.
@@ -8274,8 +8336,9 @@
si.deliveryCount++;
if (si.targetPermissionUid >= 0) {
grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
- r.packageName, si.intent, si);
+ r.packageName, si.intent, si.getUriPermissionsLocked());
}
+ if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
bumpServiceExecutingLocked(r);
if (!oomAdjusted) {
oomAdjusted = true;
@@ -8292,6 +8355,7 @@
} catch (RemoteException e) {
// Remote process gone... we'll let the normal cleanup take
// care of this.
+ if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
break;
} catch (Exception e) {
Slog.w(TAG, "Unexpected exception", e);
@@ -8308,9 +8372,9 @@
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
+ if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
+ + " in " + i + ": shouldUnbind=" + i.hasBound);
bumpServiceExecutingLocked(r);
- if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
- + ": shouldUnbind=" + i.hasBound);
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
if (!rebind) {
i.requested = true;
@@ -8318,6 +8382,7 @@
i.hasBound = true;
i.doRebind = false;
} catch (RemoteException e) {
+ if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
return false;
}
}
@@ -8344,13 +8409,12 @@
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
app.services.add(r);
+ if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
bumpServiceExecutingLocked(r);
updateLruProcessLocked(app, true, true);
boolean created = false;
try {
- if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
- + r.name + " " + r.intent);
mStringBuilder.setLength(0);
r.intent.getIntent().toShortString(mStringBuilder, false, true);
EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
@@ -8510,8 +8574,7 @@
return true;
}
- if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
- + " " + r.intent);
+ if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
// We are now bringing the service up, so no longer in the
// restarting state.
@@ -8562,27 +8625,30 @@
if (!force) {
// XXX should probably keep a count of the number of auto-create
// connections directly in the service.
- Iterator<ConnectionRecord> it = r.connections.values().iterator();
+ Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
while (it.hasNext()) {
- ConnectionRecord cr = it.next();
- if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
- return;
+ ArrayList<ConnectionRecord> cr = it.next();
+ for (int i=0; i<cr.size(); i++) {
+ if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
+ return;
+ }
}
}
}
// Report to all of the connections that the service is no longer
// available.
- Iterator<ConnectionRecord> it = r.connections.values().iterator();
+ Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
while (it.hasNext()) {
- ConnectionRecord c = it.next();
- try {
- // todo: shouldn't be a synchronous call!
- c.conn.connected(r.name, null);
- } catch (Exception e) {
- Slog.w(TAG, "Failure disconnecting service " + r.name +
- " to connection " + c.conn.asBinder() +
- " (in " + c.binding.client.processName + ")", e);
+ ArrayList<ConnectionRecord> c = it.next();
+ for (int i=0; i<c.size(); i++) {
+ try {
+ c.get(i).conn.connected(r.name, null);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failure disconnecting service " + r.name +
+ " to connection " + c.get(i).conn.asBinder() +
+ " (in " + c.get(i).binding.client.processName + ")", e);
+ }
}
}
}
@@ -8596,6 +8662,8 @@
+ ": hasBound=" + ibr.hasBound);
if (r.app != null && r.app.thread != null && ibr.hasBound) {
try {
+ if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
+ + " for " + ibr);
bumpServiceExecutingLocked(r);
updateOomAdjLocked(r.app);
ibr.hasBound = false;
@@ -8610,15 +8678,13 @@
}
}
- if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
- + " " + r.intent);
+ if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
System.identityHashCode(r), r.shortName,
(r.app != null) ? r.app.pid : -1);
mServices.remove(r.name);
mServicesByIntent.remove(r.intent);
- if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
r.totalRestartCount = 0;
unscheduleServiceRestartLocked(r);
@@ -8627,8 +8693,7 @@
for (int i=0; i<N; i++) {
if (mPendingServices.get(i) == r) {
mPendingServices.remove(i);
- if (DEBUG_SERVICE) Slog.v(
- TAG, "Removed pending service: " + r.shortName);
+ if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
i--;
N--;
}
@@ -8650,8 +8715,11 @@
r.app.services.remove(r);
if (r.app.thread != null) {
try {
- if (DEBUG_SERVICE) Slog.v(TAG,
- "Stopping service: " + r.shortName);
+ if (DEBUG_SERVICE) {
+ RuntimeException here = new RuntimeException();
+ here.fillInStackTrace();
+ Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
+ }
bumpServiceExecutingLocked(r);
mStoppingServices.add(r);
updateOomAdjLocked(r.app);
@@ -8664,11 +8732,11 @@
updateServiceForegroundLocked(r.app, false);
} else {
if (DEBUG_SERVICE) Slog.v(
- TAG, "Removed service that has no process: " + r.shortName);
+ TAG, "Removed service that has no process: " + r);
}
} else {
if (DEBUG_SERVICE) Slog.v(
- TAG, "Removed service that is not running: " + r.shortName);
+ TAG, "Removed service that is not running: " + r);
}
}
@@ -8703,8 +8771,7 @@
int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service);
if (unscheduleServiceRestartLocked(r)) {
- if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
- + r.shortName);
+ if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
}
r.startRequested = true;
r.callStart = false;
@@ -8998,7 +9065,7 @@
if (unscheduleServiceRestartLocked(s)) {
if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
- + s.shortName);
+ + s);
}
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
@@ -9006,7 +9073,12 @@
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
- s.connections.put(binder, c);
+ ArrayList<ConnectionRecord> clist = s.connections.get(binder);
+ if (clist == null) {
+ clist = new ArrayList<ConnectionRecord>();
+ s.connections.put(binder, clist);
+ }
+ clist.add(c);
b.connections.add(c);
if (activity != null) {
if (activity.connections == null) {
@@ -9015,7 +9087,12 @@
activity.connections.add(c);
}
b.client.connections.add(c);
- mServiceConnections.put(binder, c);
+ clist = mServiceConnections.get(binder);
+ if (clist == null) {
+ clist = new ArrayList<ConnectionRecord>();
+ mServiceConnections.put(binder, clist);
+ }
+ clist.add(c);
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
@@ -9066,7 +9143,13 @@
IBinder binder = c.conn.asBinder();
AppBindRecord b = c.binding;
ServiceRecord s = b.service;
- s.connections.remove(binder);
+ ArrayList<ConnectionRecord> clist = s.connections.get(binder);
+ if (clist != null) {
+ clist.remove(c);
+ if (clist.size() == 0) {
+ s.connections.remove(binder);
+ }
+ }
b.connections.remove(c);
if (c.activity != null && c.activity != skipAct) {
if (c.activity.connections != null) {
@@ -9076,7 +9159,13 @@
if (b.client != skipApp) {
b.client.connections.remove(c);
}
- mServiceConnections.remove(binder);
+ clist = mServiceConnections.get(binder);
+ if (clist != null) {
+ clist.remove(c);
+ if (clist.size() == 0) {
+ mServiceConnections.remove(binder);
+ }
+ }
if (b.connections.size() == 0) {
b.intent.apps.remove(b.client);
@@ -9087,6 +9176,8 @@
if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
&& b.intent.hasBound) {
try {
+ if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
+ + " from " + b);
bumpServiceExecutingLocked(s);
updateOomAdjLocked(s.app);
b.intent.hasBound = false;
@@ -9109,8 +9200,8 @@
synchronized (this) {
IBinder binder = connection.asBinder();
if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
- ConnectionRecord r = mServiceConnections.get(binder);
- if (r == null) {
+ ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
+ if (clist == null) {
Slog.w(TAG, "Unbind failed: could not find connection for "
+ connection.asBinder());
return false;
@@ -9118,11 +9209,14 @@
final long origId = Binder.clearCallingIdentity();
- removeConnectionLocked(r, null, null);
+ while (clist.size() > 0) {
+ ConnectionRecord r = clist.get(0);
+ removeConnectionLocked(r, null, null);
- if (r.binding.service.app != null) {
- // This could have made the service less important.
- updateOomAdjLocked(r.binding.service.app);
+ if (r.binding.service.app != null) {
+ // This could have made the service less important.
+ updateOomAdjLocked(r.binding.service.app);
+ }
}
Binder.restoreCallingIdentity(origId);
@@ -9145,7 +9239,7 @@
final long origId = Binder.clearCallingIdentity();
- if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
+ if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
+ " " + intent + ": " + service);
if (r != null) {
Intent.FilterComparison filter
@@ -9156,26 +9250,29 @@
b.requested = true;
b.received = true;
if (r.connections.size() > 0) {
- Iterator<ConnectionRecord> it
+ Iterator<ArrayList<ConnectionRecord>> it
= r.connections.values().iterator();
while (it.hasNext()) {
- ConnectionRecord c = it.next();
- if (!filter.equals(c.binding.intent.intent)) {
- if (DEBUG_SERVICE) Slog.v(
- TAG, "Not publishing to: " + c);
- if (DEBUG_SERVICE) Slog.v(
- TAG, "Bound intent: " + c.binding.intent.intent);
- if (DEBUG_SERVICE) Slog.v(
- TAG, "Published intent: " + intent);
- continue;
- }
- if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
- try {
- c.conn.connected(r.name, service);
- } catch (Exception e) {
- Slog.w(TAG, "Failure sending service " + r.name +
- " to connection " + c.conn.asBinder() +
- " (in " + c.binding.client.processName + ")", e);
+ ArrayList<ConnectionRecord> clist = it.next();
+ for (int i=0; i<clist.size(); i++) {
+ ConnectionRecord c = clist.get(i);
+ if (!filter.equals(c.binding.intent.intent)) {
+ if (DEBUG_SERVICE) Slog.v(
+ TAG, "Not publishing to: " + c);
+ if (DEBUG_SERVICE) Slog.v(
+ TAG, "Bound intent: " + c.binding.intent.intent);
+ if (DEBUG_SERVICE) Slog.v(
+ TAG, "Published intent: " + intent);
+ continue;
+ }
+ if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
+ try {
+ c.conn.connected(r.name, service);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failure sending service " + r.name +
+ " to connection " + c.conn.asBinder() +
+ " (in " + c.binding.client.processName + ")", e);
+ }
}
}
}
@@ -9236,9 +9333,6 @@
ServiceRecord r = (ServiceRecord)token;
boolean inStopping = mStoppingServices.contains(token);
if (r != null) {
- if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
- + ": nesting=" + r.executeNesting
- + ", inStopping=" + inStopping);
if (r != token) {
Slog.w(TAG, "Done executing service " + r.name
+ " with incorrect token: given " + token
@@ -9295,13 +9389,16 @@
serviceDoneExecutingLocked(r, inStopping);
Binder.restoreCallingIdentity(origId);
} else {
- Slog.w(TAG, "Done executing unknown service " + r.name
- + " with token " + token);
+ Slog.w(TAG, "Done executing unknown service from pid "
+ + Binder.getCallingPid());
}
}
}
public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
+ if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
+ + ": nesting=" + r.executeNesting
+ + ", inStopping=" + inStopping + ", app=" + r.app);
r.executeNesting--;
if (r.executeNesting <= 0 && r.app != null) {
r.app.executingServices.remove(r);
@@ -9309,6 +9406,7 @@
mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
}
if (inStopping) {
+ if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
mStoppingServices.remove(r);
}
updateOomAdjLocked(r.app);
@@ -11099,61 +11197,64 @@
}
if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
|| schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
- Iterator<ConnectionRecord> kt
+ Iterator<ArrayList<ConnectionRecord>> kt
= s.connections.values().iterator();
while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
- // XXX should compute this based on the max of
- // all connected clients.
- ConnectionRecord cr = kt.next();
- if (cr.binding.client == app) {
- // Binding to ourself is not interesting.
- continue;
- }
- if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
- ProcessRecord client = cr.binding.client;
- int myHiddenAdj = hiddenAdj;
- if (myHiddenAdj > client.hiddenAdj) {
- if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
- myHiddenAdj = client.hiddenAdj;
- } else {
- myHiddenAdj = VISIBLE_APP_ADJ;
+ ArrayList<ConnectionRecord> clist = kt.next();
+ for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
+ // XXX should compute this based on the max of
+ // all connected clients.
+ ConnectionRecord cr = clist.get(i);
+ if (cr.binding.client == app) {
+ // Binding to ourself is not interesting.
+ continue;
+ }
+ if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
+ ProcessRecord client = cr.binding.client;
+ int myHiddenAdj = hiddenAdj;
+ if (myHiddenAdj > client.hiddenAdj) {
+ if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
+ myHiddenAdj = client.hiddenAdj;
+ } else {
+ myHiddenAdj = VISIBLE_APP_ADJ;
+ }
+ }
+ int clientAdj = computeOomAdjLocked(
+ client, myHiddenAdj, TOP_APP, true);
+ if (adj > clientAdj) {
+ adj = clientAdj >= VISIBLE_APP_ADJ
+ ? clientAdj : VISIBLE_APP_ADJ;
+ if (!client.hidden) {
+ app.hidden = false;
+ }
+ app.adjType = "service";
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+ .REASON_SERVICE_IN_USE;
+ app.adjSource = cr.binding.client;
+ app.adjTarget = s.name;
+ }
+ if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
+ if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
+ schedGroup = Process.THREAD_GROUP_DEFAULT;
+ }
}
}
- int clientAdj = computeOomAdjLocked(
- client, myHiddenAdj, TOP_APP, true);
- if (adj > clientAdj) {
- adj = clientAdj >= VISIBLE_APP_ADJ
- ? clientAdj : VISIBLE_APP_ADJ;
- if (!client.hidden) {
- app.hidden = false;
- }
+ ActivityRecord a = cr.activity;
+ //if (a != null) {
+ // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
+ //}
+ if (a != null && adj > FOREGROUND_APP_ADJ &&
+ (a.state == ActivityState.RESUMED
+ || a.state == ActivityState.PAUSING)) {
+ adj = FOREGROUND_APP_ADJ;
+ schedGroup = Process.THREAD_GROUP_DEFAULT;
+ app.hidden = false;
app.adjType = "service";
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_SERVICE_IN_USE;
- app.adjSource = cr.binding.client;
+ app.adjSource = a;
app.adjTarget = s.name;
}
- if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
- if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
- schedGroup = Process.THREAD_GROUP_DEFAULT;
- }
- }
- }
- ActivityRecord a = cr.activity;
- //if (a != null) {
- // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
- //}
- if (a != null && adj > FOREGROUND_APP_ADJ &&
- (a.state == ActivityState.RESUMED
- || a.state == ActivityState.PAUSING)) {
- adj = FOREGROUND_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_DEFAULT;
- app.hidden = false;
- app.adjType = "service";
- app.adjTypeCode = ActivityManager.RunningAppProcessInfo
- .REASON_SERVICE_IN_USE;
- app.adjSource = a;
- app.adjTarget = s.name;
}
}
}
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 80a41b7..62be918 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -44,7 +44,7 @@
/**
* An entry in the history stack, representing an activity.
*/
-class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwner {
+class ActivityRecord extends IApplicationToken.Stub {
final ActivityManagerService service; // owner
final ActivityStack stack; // owner
final ActivityInfo info; // all about me
@@ -78,8 +78,7 @@
HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
ArrayList newIntents; // any pending new intents for single-top mode
HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
- HashSet<UriPermission> readUriPermissions; // special access to reading uris.
- HashSet<UriPermission> writeUriPermissions; // special access to writing uris.
+ UriPermissionOwner uriPermissions; // current special URI access perms.
ProcessRecord app; // if non-null, hosting application
Bitmap thumbnail; // icon representation of paused screen
CharSequence description; // textual description of paused screen
@@ -141,11 +140,15 @@
if (pendingResults != null) {
pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults);
}
- if (readUriPermissions != null) {
- pw.print(prefix); pw.print("readUriPermissions="); pw.println(readUriPermissions);
- }
- if (writeUriPermissions != null) {
- pw.print(prefix); pw.print("writeUriPermissions="); pw.println(writeUriPermissions);
+ if (uriPermissions != null) {
+ if (uriPermissions.readUriPermissions != null) {
+ pw.print(prefix); pw.print("readUriPermissions=");
+ pw.println(uriPermissions.readUriPermissions);
+ }
+ if (uriPermissions.writeUriPermissions != null) {
+ pw.print(prefix); pw.print("writeUriPermissions=");
+ pw.println(uriPermissions.writeUriPermissions);
+ }
}
pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
pw.print(" haveState="); pw.print(haveState);
@@ -301,6 +304,13 @@
}
}
+ UriPermissionOwner getUriPermissionsLocked() {
+ if (uriPermissions == null) {
+ uriPermissions = new UriPermissionOwner(service, this);
+ }
+ return uriPermissions;
+ }
+
void addResultLocked(ActivityRecord from, String resultWho,
int requestCode, int resultCode,
Intent resultData) {
@@ -350,7 +360,7 @@
intent = new Intent(intent);
ar.add(intent);
service.grantUriPermissionFromIntentLocked(callingUid, packageName,
- intent, this);
+ intent, getUriPermissionsLocked());
app.thread.scheduleNewIntent(ar, this);
sent = true;
} catch (RemoteException e) {
@@ -367,27 +377,9 @@
}
void removeUriPermissionsLocked() {
- if (readUriPermissions != null) {
- for (UriPermission perm : readUriPermissions) {
- perm.readOwners.remove(this);
- if (perm.readOwners.size() == 0 && (perm.globalModeFlags
- &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
- perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
- service.removeUriPermissionIfNeededLocked(perm);
- }
- }
- readUriPermissions = null;
- }
- if (writeUriPermissions != null) {
- for (UriPermission perm : writeUriPermissions) {
- perm.writeOwners.remove(this);
- if (perm.writeOwners.size() == 0 && (perm.globalModeFlags
- &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
- perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
- service.removeUriPermissionIfNeededLocked(perm);
- }
- }
- writeUriPermissions = null;
+ if (uriPermissions != null) {
+ uriPermissions.removeUriPermissionsLocked();
+ uriPermissions = null;
}
}
@@ -578,38 +570,6 @@
state == ActivityState.RESUMED;
}
- @Override
- public void addReadPermission(UriPermission perm) {
- if (readUriPermissions == null) {
- readUriPermissions = new HashSet<UriPermission>();
- }
- readUriPermissions.add(perm);
- }
-
- @Override
- public void addWritePermission(UriPermission perm) {
- if (writeUriPermissions == null) {
- writeUriPermissions = new HashSet<UriPermission>();
- }
- writeUriPermissions.add(perm);
- }
-
- @Override
- public void removeReadPermission(UriPermission perm) {
- readUriPermissions.remove(perm);
- if (readUriPermissions.size() == 0) {
- readUriPermissions = null;
- }
- }
-
- @Override
- public void removeWritePermission(UriPermission perm) {
- writeUriPermissions.remove(perm);
- if (writeUriPermissions.size() == 0) {
- writeUriPermissions = null;
- }
- }
-
public String toString() {
if (stringName != null) {
return stringName;
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index a5f7e96..a99b48c 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -2327,12 +2327,12 @@
if (grantedUriPermissions != null && callingUid > 0) {
for (int i=0; i<grantedUriPermissions.length; i++) {
mService.grantUriPermissionLocked(callingUid, r.packageName,
- grantedUriPermissions[i], grantedMode, r);
+ grantedUriPermissions[i], grantedMode, r.getUriPermissionsLocked());
}
}
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
- intent, r);
+ intent, r.getUriPermissionsLocked());
if (newTask) {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
@@ -2557,7 +2557,7 @@
if (callingUid > 0) {
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
- data, r);
+ data, r.getUriPermissionsLocked());
}
if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
@@ -2885,7 +2885,7 @@
+ " res=" + resultCode + " data=" + resultData);
if (r.info.applicationInfo.uid > 0) {
mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
- r.packageName, resultData, r);
+ r.packageName, resultData, r.getUriPermissionsLocked());
}
resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
resultData);
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 255fbe3..f35a68e 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -72,8 +72,8 @@
final HashMap<Intent.FilterComparison, IntentBindRecord> bindings
= new HashMap<Intent.FilterComparison, IntentBindRecord>();
// All active bindings to the service.
- final HashMap<IBinder, ConnectionRecord> connections
- = new HashMap<IBinder, ConnectionRecord>();
+ final HashMap<IBinder, ArrayList<ConnectionRecord>> connections
+ = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
// IBinder -> ConnectionRecord of all bound clients
ProcessRecord app; // where this service is running or null.
@@ -96,7 +96,7 @@
String stringName; // caching of toString
- static class StartItem implements UriPermissionOwner {
+ static class StartItem {
final ServiceRecord sr;
final int id;
final Intent intent;
@@ -104,12 +104,10 @@
long deliveredTime;
int deliveryCount;
int doneExecutingCount;
+ UriPermissionOwner uriPermissions;
String stringName; // caching of toString
- HashSet<UriPermission> readUriPermissions; // special access to reading uris.
- HashSet<UriPermission> writeUriPermissions; // special access to writing uris.
-
StartItem(ServiceRecord _sr, int _id, Intent _intent, int _targetPermissionUid) {
sr = _sr;
id = _id;
@@ -117,60 +115,17 @@
targetPermissionUid = _targetPermissionUid;
}
+ UriPermissionOwner getUriPermissionsLocked() {
+ if (uriPermissions == null) {
+ uriPermissions = new UriPermissionOwner(sr.ams, this);
+ }
+ return uriPermissions;
+ }
+
void removeUriPermissionsLocked() {
- if (readUriPermissions != null) {
- for (UriPermission perm : readUriPermissions) {
- perm.readOwners.remove(this);
- if (perm.readOwners.size() == 0 && (perm.globalModeFlags
- &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
- perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
- sr.ams.removeUriPermissionIfNeededLocked(perm);
- }
- }
- readUriPermissions = null;
- }
- if (writeUriPermissions != null) {
- for (UriPermission perm : writeUriPermissions) {
- perm.writeOwners.remove(this);
- if (perm.writeOwners.size() == 0 && (perm.globalModeFlags
- &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
- perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
- sr.ams.removeUriPermissionIfNeededLocked(perm);
- }
- }
- writeUriPermissions = null;
- }
- }
-
- @Override
- public void addReadPermission(UriPermission perm) {
- if (readUriPermissions == null) {
- readUriPermissions = new HashSet<UriPermission>();
- }
- readUriPermissions.add(perm);
- }
-
- @Override
- public void addWritePermission(UriPermission perm) {
- if (writeUriPermissions == null) {
- writeUriPermissions = new HashSet<UriPermission>();
- }
- writeUriPermissions.add(perm);
- }
-
- @Override
- public void removeReadPermission(UriPermission perm) {
- readUriPermissions.remove(perm);
- if (readUriPermissions.size() == 0) {
- readUriPermissions = null;
- }
- }
-
- @Override
- public void removeWritePermission(UriPermission perm) {
- writeUriPermissions.remove(perm);
- if (writeUriPermissions.size() == 0) {
- writeUriPermissions = null;
+ if (uriPermissions != null) {
+ uriPermissions.removeUriPermissionsLocked();
+ uriPermissions = null;
}
}
@@ -218,13 +173,15 @@
pw.print(prefix); pw.print(" targetPermissionUid=");
pw.println(si.targetPermissionUid);
}
- if (si.readUriPermissions != null) {
- pw.print(prefix); pw.print(" readUriPermissions=");
- pw.println(si.readUriPermissions);
- }
- if (si.writeUriPermissions != null) {
- pw.print(prefix); pw.print(" writeUriPermissions=");
- pw.println(si.writeUriPermissions);
+ if (si.uriPermissions != null) {
+ if (si.uriPermissions.readUriPermissions != null) {
+ pw.print(prefix); pw.print(" readUriPermissions=");
+ pw.println(si.uriPermissions.readUriPermissions);
+ }
+ if (si.uriPermissions.writeUriPermissions != null) {
+ pw.print(prefix); pw.print(" writeUriPermissions=");
+ pw.println(si.uriPermissions.writeUriPermissions);
+ }
}
}
}
@@ -296,10 +253,12 @@
}
if (connections.size() > 0) {
pw.print(prefix); pw.println("All Connections:");
- Iterator<ConnectionRecord> it = connections.values().iterator();
+ Iterator<ArrayList<ConnectionRecord>> it = connections.values().iterator();
while (it.hasNext()) {
- ConnectionRecord c = it.next();
- pw.print(prefix); pw.print(" "); pw.println(c);
+ ArrayList<ConnectionRecord> c = it.next();
+ for (int i=0; i<c.size(); i++) {
+ pw.print(prefix); pw.print(" "); pw.println(c.get(i));
+ }
}
}
}
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
index 93c59cc..c95546e 100644
--- a/services/java/com/android/server/am/UriPermission.java
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -22,13 +22,14 @@
import java.io.PrintWriter;
import java.util.HashSet;
-interface UriPermissionOwner {
- void addReadPermission(UriPermission perm);
- void addWritePermission(UriPermission perm);
- void removeReadPermission(UriPermission perm);
- void removeWritePermission(UriPermission perm);
-}
-
+/**
+ * Description of a permission granted to an app to access a particular URI.
+ *
+ * CTS tests for this functionality can be run with "runtest cts-appsecurity".
+ *
+ * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert
+ * /src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
+ */
class UriPermission {
final int uid;
final Uri uri;
diff --git a/services/java/com/android/server/am/UriPermissionOwner.java b/services/java/com/android/server/am/UriPermissionOwner.java
new file mode 100644
index 0000000..99c82e6
--- /dev/null
+++ b/services/java/com/android/server/am/UriPermissionOwner.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2010 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.server.am;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.IBinder;
+
+import java.util.HashSet;
+import java.util.Iterator;
+
+class UriPermissionOwner {
+ final ActivityManagerService service;
+ final Object owner;
+
+ Binder externalToken;
+
+ HashSet<UriPermission> readUriPermissions; // special access to reading uris.
+ HashSet<UriPermission> writeUriPermissions; // special access to writing uris.
+
+ class ExternalToken extends Binder {
+ UriPermissionOwner getOwner() {
+ return UriPermissionOwner.this;
+ }
+ }
+
+ UriPermissionOwner(ActivityManagerService _service, Object _owner) {
+ service = _service;
+ owner = _owner;
+ }
+
+ Binder getExternalTokenLocked() {
+ if (externalToken != null) {
+ externalToken = new ExternalToken();
+ }
+ return externalToken;
+ }
+
+ static UriPermissionOwner fromExternalToken(IBinder token) {
+ if (token instanceof ExternalToken) {
+ return ((ExternalToken)token).getOwner();
+ }
+ return null;
+ }
+
+ void removeUriPermissionsLocked() {
+ removeUriPermissionsLocked(Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ }
+
+ void removeUriPermissionsLocked(int mode) {
+ if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
+ && readUriPermissions != null) {
+ for (UriPermission perm : readUriPermissions) {
+ perm.readOwners.remove(this);
+ if (perm.readOwners.size() == 0 && (perm.globalModeFlags
+ &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
+ perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
+ service.removeUriPermissionIfNeededLocked(perm);
+ }
+ }
+ readUriPermissions = null;
+ }
+ if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
+ && writeUriPermissions != null) {
+ for (UriPermission perm : writeUriPermissions) {
+ perm.writeOwners.remove(this);
+ if (perm.writeOwners.size() == 0 && (perm.globalModeFlags
+ &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
+ perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+ service.removeUriPermissionIfNeededLocked(perm);
+ }
+ }
+ writeUriPermissions = null;
+ }
+ }
+
+ void removeUriPermissionLocked(Uri uri, int mode) {
+ if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
+ && readUriPermissions != null) {
+ Iterator<UriPermission> it = readUriPermissions.iterator();
+ while (it.hasNext()) {
+ UriPermission perm = it.next();
+ if (uri.equals(perm.uri)) {
+ perm.readOwners.remove(this);
+ if (perm.readOwners.size() == 0 && (perm.globalModeFlags
+ &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
+ perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
+ service.removeUriPermissionIfNeededLocked(perm);
+ }
+ it.remove();
+ }
+ }
+ if (readUriPermissions.size() == 0) {
+ readUriPermissions = null;
+ }
+ }
+ if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
+ && writeUriPermissions != null) {
+ Iterator<UriPermission> it = writeUriPermissions.iterator();
+ while (it.hasNext()) {
+ UriPermission perm = it.next();
+ if (uri.equals(perm.uri)) {
+ perm.writeOwners.remove(this);
+ if (perm.writeOwners.size() == 0 && (perm.globalModeFlags
+ &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
+ perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+ service.removeUriPermissionIfNeededLocked(perm);
+ }
+ it.remove();
+ }
+ }
+ if (writeUriPermissions.size() == 0) {
+ writeUriPermissions = null;
+ }
+ }
+ }
+
+ public void addReadPermission(UriPermission perm) {
+ if (readUriPermissions == null) {
+ readUriPermissions = new HashSet<UriPermission>();
+ }
+ readUriPermissions.add(perm);
+ }
+
+ public void addWritePermission(UriPermission perm) {
+ if (writeUriPermissions == null) {
+ writeUriPermissions = new HashSet<UriPermission>();
+ }
+ writeUriPermissions.add(perm);
+ }
+
+ public void removeReadPermission(UriPermission perm) {
+ readUriPermissions.remove(perm);
+ if (readUriPermissions.size() == 0) {
+ readUriPermissions = null;
+ }
+ }
+
+ public void removeWritePermission(UriPermission perm) {
+ writeUriPermissions.remove(perm);
+ if (writeUriPermissions.size() == 0) {
+ writeUriPermissions = null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return owner.toString();
+ }
+}
diff --git a/services/java/com/android/server/sip/SipService.java b/services/java/com/android/server/sip/SipService.java
index 1142136..3dcaff6 100644
--- a/services/java/com/android/server/sip/SipService.java
+++ b/services/java/com/android/server/sip/SipService.java
@@ -32,6 +32,7 @@
import android.net.sip.SipSessionAdapter;
import android.net.sip.SipSessionState;
import android.net.wifi.WifiManager;
+import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -97,6 +98,7 @@
}
public void open(SipProfile localProfile) {
+ localProfile.setCallingUid(Binder.getCallingUid());
if (localProfile.getAutoRegistration()) {
openToReceiveCalls(localProfile);
} else {
@@ -119,6 +121,7 @@
public synchronized void open3(SipProfile localProfile,
String incomingCallBroadcastAction, ISipSessionListener listener) {
+ localProfile.setCallingUid(Binder.getCallingUid());
if (TextUtils.isEmpty(incomingCallBroadcastAction)) {
throw new RuntimeException(
"empty broadcast action for incoming call");
@@ -165,6 +168,7 @@
public synchronized ISipSession createSession(SipProfile localProfile,
ISipSessionListener listener) {
+ localProfile.setCallingUid(Binder.getCallingUid());
if (!mConnected) return null;
try {
SipSessionGroupExt group = createGroup(localProfile);
@@ -362,16 +366,7 @@
private SipProfile duplicate(SipProfile p) {
try {
- return new SipProfile.Builder(p.getUserName(), p.getSipDomain())
- .setProfileName(p.getProfileName())
- .setPassword("*")
- .setPort(p.getPort())
- .setProtocol(p.getProtocol())
- .setOutboundProxy(p.getProxyAddress())
- .setSendKeepAlive(p.getSendKeepAlive())
- .setAutoRegistration(p.getAutoRegistration())
- .setDisplayName(p.getDisplayName())
- .build();
+ return new SipProfile.Builder(p).setPassword("*").build();
} catch (Exception e) {
Log.wtf(TAG, "duplicate()", e);
throw new RuntimeException("duplicate profile", e);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 212c08b..194c295 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -163,9 +163,13 @@
const uint32_t hwFlags = hw.getFlags();
mFormat = format;
- mReqFormat = format;
mWidth = w;
mHeight = h;
+
+ mReqFormat = format;
+ mReqWidth = w;
+ mReqHeight = h;
+
mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
@@ -253,12 +257,16 @@
} else {
slowpath:
GGLSurface t;
- status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
- LOGE_IF(res, "error %d (%s) locking buffer %p",
- res, strerror(res), buffer.get());
- if (res == NO_ERROR) {
- mBufferManager.loadTexture(dirty, t);
- buffer->unlock();
+ if (buffer->usage & GRALLOC_USAGE_SW_READ_MASK) {
+ status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
+ LOGE_IF(res, "error %d (%s) locking buffer %p",
+ res, strerror(res), buffer.get());
+ if (res == NO_ERROR) {
+ mBufferManager.loadTexture(dirty, t);
+ buffer->unlock();
+ }
+ } else {
+ // we can't do anything
}
}
}
@@ -357,16 +365,22 @@
uint32_t w, h, f;
{ // scope for the lock
Mutex::Autolock _l(mLock);
- const bool fixedSizeChanged = mFixedSize != (reqWidth && reqHeight);
- const bool formatChanged = mReqFormat != reqFormat;
- mReqWidth = reqWidth;
- mReqHeight = reqHeight;
- mReqFormat = reqFormat;
- mFixedSize = reqWidth && reqHeight;
- w = reqWidth ? reqWidth : mWidth;
- h = reqHeight ? reqHeight : mHeight;
- f = reqFormat ? reqFormat : mFormat;
- if (fixedSizeChanged || formatChanged) {
+
+ // zero means default
+ if (!reqFormat) reqFormat = mFormat;
+ if (!reqWidth) reqWidth = mWidth;
+ if (!reqHeight) reqHeight = mHeight;
+
+ w = reqWidth;
+ h = reqHeight;
+ f = reqFormat;
+
+ if ((reqWidth != mReqWidth) || (reqHeight != mReqHeight) ||
+ (reqFormat != mReqFormat)) {
+ mReqWidth = reqWidth;
+ mReqHeight = reqHeight;
+ mReqFormat = reqFormat;
+
lcblk->reallocateAllExcept(index);
}
}
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 980affa..12df44e 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -691,8 +691,8 @@
* Stop the playing DTMF tone. Ignored if there is no playing DTMF
* tone or no active call.
*/
- public void stopDtmf(Phone phone) {
- phone.stopDtmf();
+ public void stopDtmf() {
+ if (hasActiveFgCall()) getFgPhone().stopDtmf();
}
/**
@@ -709,7 +709,7 @@
* @param onComplete is the callback message when the action is processed by BP
*
*/
- public boolean sendBurstDtmf(Phone phone, String dtmfString, int on, int off, Message onComplete) {
+ public boolean sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
if (hasActiveFgCall()) {
getActiveFgCall().getPhone().sendBurstDtmf(dtmfString, on, off, onComplete);
return true;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index b39556a..8d77f76 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -224,6 +224,7 @@
mCM.unregisterForNVReady(this); //EVENT_NV_READY
mSST.unregisterForNetworkAttach(this); //EVENT_REGISTERED_TO_NETWORK
mCM.unSetOnSuppServiceNotification(this);
+ removeCallbacks(mExitEcmRunnable);
mPendingMmis.clear();
@@ -256,6 +257,7 @@
this.mSST = null;
this.mEriManager = null;
this.mCcatService = null;
+ this.mExitEcmRunnable = null;
}
protected void finalize() {
diff --git a/tests/CoreTests/android/core/JavaPerformanceTests.java b/tests/CoreTests/android/core/JavaPerformanceTests.java
index fbe70cc..95075ea 100644
--- a/tests/CoreTests/android/core/JavaPerformanceTests.java
+++ b/tests/CoreTests/android/core/JavaPerformanceTests.java
@@ -23,7 +23,6 @@
public static String[] children() {
return new String[] {
- StringTest.class.getName(),
HashMapPerformanceTest.class.getName(),
ArrayListPerformanceTest.class.getName(),
TreeMapPerformanceTest.class.getName(),
diff --git a/tests/CoreTests/android/core/StringTest.java b/tests/CoreTests/android/core/StringTest.java
deleted file mode 100644
index 128531c..0000000
--- a/tests/CoreTests/android/core/StringTest.java
+++ /dev/null
@@ -1,951 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import java.util.Locale;
-
-import android.test.PerformanceTestBase;
-import android.test.PerformanceTestCase;
-
-public class StringTest extends PerformanceTestBase {
- public static final int ITERATIONS = 1000;
- public static final String STATIC_STRING_01 = "Hello Android";
- public static final String STATIC_STRING_02 =
- "Remember, today is the tomorrow you worried about yesterday";
- public static final char[] STATIC_CHAR_ARRAY =
- {'N', 'A', 'N', 'D', 'R', 'O', 'I', 'D'};
- public static StringBuffer STATIC_SBUF = new StringBuffer(STATIC_STRING_02);
-
- @Override
- public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
- intermediates.setInternalIterations(ITERATIONS);
- return 0;
- }
-
- /** Create an empty String object* */
-
- public void testStringCreate() {
- String rString;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = new String();
- rString = new String();
- rString = new String();
- rString = new String();
- rString = new String();
- rString = new String();
- rString = new String();
- rString = new String();
- rString = new String();
- rString = new String();
- }
- }
-
- /** Create an initialised String object* */
-
- public void testStringCreate1() {
- String rString, str = STATIC_STRING_01;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = new String(str);
- rString = new String(str);
- rString = new String(str);
- rString = new String(str);
- rString = new String(str);
- rString = new String(str);
- rString = new String(str);
- rString = new String(str);
- rString = new String(str);
- rString = new String(str); // 10
- }
- }
-
- /** equals() with for loop* */
- public void testStringEquals() {
- String mString = new String(STATIC_STRING_01);
- String str = STATIC_STRING_01;
- boolean result;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- result = mString.equals(str);
- result = mString.equals(str);
- result = mString.equals(str);
- result = mString.equals(str);
- result = mString.equals(str);
- result = mString.equals(str);
- result = mString.equals(str);
- result = mString.equals(str);
- result = mString.equals(str);
- result = mString.equals(str);
- }
- }
-
- /**
- * ContentEquals- Comparing the content of a String with that of a String
- * Buffer*
- */
-
- public void testStringContentEquals() {
- StringBuffer sBuf = new StringBuffer(STATIC_STRING_01);
- String str = STATIC_STRING_01;
- boolean result;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- result = str.contentEquals(sBuf);
- result = str.contentEquals(sBuf);
- result = str.contentEquals(sBuf);
- result = str.contentEquals(sBuf);
- result = str.contentEquals(sBuf);
- result = str.contentEquals(sBuf);
- result = str.contentEquals(sBuf);
- result = str.contentEquals(sBuf);
- result = str.contentEquals(sBuf);
- result = str.contentEquals(sBuf);
- }
- }
-
- /** Compare string objects lexicographically using compareTo() with for loop* */
-
- public void testStringCompareTo() {
- String str1 = new String(STATIC_STRING_01);
- String str2 = STATIC_STRING_01;
- int result;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- result = str1.compareTo(str2);
- result = str1.compareTo(str2);
- result = str1.compareTo(str2);
- result = str1.compareTo(str2);
- result = str1.compareTo(str2);
- result = str1.compareTo(str2);
- result = str1.compareTo(str2);
- result = str1.compareTo(str2);
- result = str1.compareTo(str2);
- result = str1.compareTo(str2);
- }
-
- }
-
- /** Compare string objects using compareToIgnorecase() with for loop* */
-
- public void testStringCompareToIgnoreCase() {
- String mString = new String(STATIC_STRING_01);
- String str2 = STATIC_STRING_01;
- int result;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- result = mString.compareToIgnoreCase(str2);
- result = mString.compareToIgnoreCase(str2);
- result = mString.compareToIgnoreCase(str2);
- result = mString.compareToIgnoreCase(str2);
- result = mString.compareToIgnoreCase(str2);
- result = mString.compareToIgnoreCase(str2);
- result = mString.compareToIgnoreCase(str2);
- result = mString.compareToIgnoreCase(str2);
- result = mString.compareToIgnoreCase(str2);
- result = mString.compareToIgnoreCase(str2);
- }
- }
-
- /** startsWith * */
-
- public void testStringstartsWith() {
- boolean result;
- String str1 = STATIC_STRING_02, str2 = "Rem";
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- result = str1.startsWith(str2);
- result = str1.startsWith(str2);
- result = str1.startsWith(str2);
- result = str1.startsWith(str2);
- result = str1.startsWith(str2);
- result = str1.startsWith(str2);
- result = str1.startsWith(str2);
- result = str1.startsWith(str2);
- result = str1.startsWith(str2);
- result = str1.startsWith(str2);
- }
- }
-
- /** startsWith(String seq, int begin) * */
-
- public void testStringstartsWith1() {
- String str1 = STATIC_STRING_02, str2 = "tom";
- int pos = 10;
- boolean result;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- result = str1.startsWith(str2, pos);
- result = str1.startsWith(str2, pos);
- result = str1.startsWith(str2, pos);
- result = str1.startsWith(str2, pos);
- result = str1.startsWith(str2, pos);
- result = str1.startsWith(str2, pos);
- result = str1.startsWith(str2, pos);
- result = str1.startsWith(str2, pos);
- result = str1.startsWith(str2, pos);
- result = str1.startsWith(str2, pos);
- }
- }
-
- /** endsWith * */
-
- public void testStringendsWith() {
- String str = STATIC_STRING_02, str1 = "day";
- boolean result;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- result = str.endsWith(str1);
- result = str.endsWith(str1);
- result = str.endsWith(str1);
- result = str.endsWith(str1);
- result = str.endsWith(str1);
- result = str.endsWith(str1);
- result = str.endsWith(str1);
- result = str.endsWith(str1);
- result = str.endsWith(str1);
- result = str.endsWith(str1);
- }
- }
-
- /**
- * indexOf to determine whether a string contains a substring
- */
- public void testStringindexOf() {
- boolean result;
- String str = STATIC_STRING_02, str1 = "tomo";
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- result = str.indexOf(str1) > 0;
- result = str.indexOf(str1) > 0;
- result = str.indexOf(str1) > 0;
- result = str.indexOf(str1) > 0;
- result = str.indexOf(str1) > 0;
- result = str.indexOf(str1) > 0;
- result = str.indexOf(str1) > 0;
- result = str.indexOf(str1) > 0;
- result = str.indexOf(str1) > 0;
- result = str.indexOf(str1) > 0;
- }
- }
-
- /** indexOf()* */
-
- public void testStringindexOf1() {
- int index;
- String str = STATIC_STRING_02;
- char c = 't';
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- index = str.indexOf(c);
- index = str.indexOf(c);
- index = str.indexOf(c);
- index = str.indexOf(c);
- index = str.indexOf(c);
- index = str.indexOf(c);
- index = str.indexOf(c);
- index = str.indexOf(c);
- index = str.indexOf(c);
- index = str.indexOf(c);
- }
-
- }
-
- /** indexOf(char c, int start)* */
- public void testStringindexOf2() {
- int index, pos = 12;
- String str = STATIC_STRING_02, str1 = "tom";
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- index = str.indexOf(str1, pos);
- index = str.indexOf(str1, pos);
- index = str.indexOf(str1, pos);
- index = str.indexOf(str1, pos);
- index = str.indexOf(str1, pos);
- index = str.indexOf(str1, pos);
- index = str.indexOf(str1, pos);
- index = str.indexOf(str1, pos);
- index = str.indexOf(str1, pos);
- index = str.indexOf(str1, pos);
- }
- }
-
- /** lastIndexOf()* */
-
- public void testStringlastIndexOf() {
- int index;
- char c = 't';
- String str = STATIC_STRING_02;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- index = str.lastIndexOf(c);
- index = str.lastIndexOf(c);
- index = str.lastIndexOf(c);
- index = str.lastIndexOf(c);
- index = str.lastIndexOf(c);
- index = str.lastIndexOf(c);
- index = str.lastIndexOf(c);
- index = str.lastIndexOf(c);
- index = str.lastIndexOf(c);
- index = str.lastIndexOf(c);
- }
- }
-
- /** lastIndexOf()* */
-
- public void testStringlastIndexOf1() {
- int index, pos = 36;
- String str = STATIC_STRING_02, str1 = "tom";
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- index = str.lastIndexOf(str1, pos);
- index = str.lastIndexOf(str1, pos);
- index = str.lastIndexOf(str1, pos);
- index = str.lastIndexOf(str1, pos);
- index = str.lastIndexOf(str1, pos);
- index = str.lastIndexOf(str1, pos);
- index = str.lastIndexOf(str1, pos);
- index = str.lastIndexOf(str1, pos);
- index = str.lastIndexOf(str1, pos);
- index = str.lastIndexOf(str1, pos);
- }
- }
-
- /**
- * contains() to determine whether a string contains a substring
- */
-
- public void testStringcontains() {
- boolean result;
- String str = STATIC_STRING_02, str1 = "tomo";
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- result = str.contains(str1);
- result = str.contains(str1);
- result = str.contains(str1);
- result = str.contains(str1);
- result = str.contains(str1);
- result = str.contains(str1);
- result = str.contains(str1);
- result = str.contains(str1);
- result = str.contains(str1);
- result = str.contains(str1);
- }
- }
-
- /** substring(int start) */
-
- public void testStringsubstring() {
- String rString;
- String str = STATIC_STRING_02;
- int index = 10;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = str.substring(index);
- rString = str.substring(index);
- rString = str.substring(index);
- rString = str.substring(index);
- rString = str.substring(index);
- rString = str.substring(index);
- rString = str.substring(index);
- rString = str.substring(index);
- rString = str.substring(index);
- rString = str.substring(index);
- }
- }
-
- /** substring(int start, int end) in a for loop* */
-
- public void testStringsubstring1() {
- String rString;
- String str = STATIC_STRING_02;
- int start = 10, end = 48;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = str.substring(start, end);
- rString = str.substring(start, end);
- rString = str.substring(start, end);
- rString = str.substring(start, end);
- rString = str.substring(start, end);
- rString = str.substring(start, end);
- rString = str.substring(start, end);
- rString = str.substring(start, end);
- rString = str.substring(start, end);
- rString = str.substring(start, end);
- }
- }
-
- /**
- * valueOf(char[] cArray) String representation of a character array
- */
- public void testStringvalueOf() {
- String rString;
- char[] cArray = STATIC_CHAR_ARRAY;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = String.valueOf(cArray);
- rString = String.valueOf(cArray);
- rString = String.valueOf(cArray);
- rString = String.valueOf(cArray);
- rString = String.valueOf(cArray);
- rString = String.valueOf(cArray);
- rString = String.valueOf(cArray);
- rString = String.valueOf(cArray);
- rString = String.valueOf(cArray);
- rString = String.valueOf(cArray);
- }
- }
-
- /** valueOf(char[] cArray, int offset, int count)* */
-
- public void testStringvalueOf1() {
- String rString;
- char[] cArray = STATIC_CHAR_ARRAY;
- int start = 1, end = 7;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = String.valueOf(cArray, start, end);
- rString = String.valueOf(cArray, start, end);
- rString = String.valueOf(cArray, start, end);
- rString = String.valueOf(cArray, start, end);
- rString = String.valueOf(cArray, start, end);
- rString = String.valueOf(cArray, start, end);
- rString = String.valueOf(cArray, start, end);
- rString = String.valueOf(cArray, start, end);
- rString = String.valueOf(cArray, start, end);
- rString = String.valueOf(cArray, start, end);
- }
- }
-
- /** Convert a string to a char Array* */
-
- public void testStringtoCharArray() {
- char[] cArray;
- String str = STATIC_STRING_02;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- cArray = str.toCharArray();
- cArray = str.toCharArray();
- cArray = str.toCharArray();
- cArray = str.toCharArray();
- cArray = str.toCharArray();
- cArray = str.toCharArray();
- cArray = str.toCharArray();
- cArray = str.toCharArray();
- cArray = str.toCharArray();
- cArray = str.toCharArray();
- }
- }
-
- /** length()* */
-
- public void testStringlength() {
- int len;
- String str = STATIC_STRING_02;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- len = str.length();
- len = str.length();
- len = str.length();
- len = str.length();
- len = str.length();
- len = str.length();
- len = str.length();
- len = str.length();
- len = str.length();
- len = str.length();
- }
- }
-
- /** hashcode()* */
-
- public void testStringhashCode() {
- int index;
- String str = STATIC_STRING_02;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- index = str.hashCode();
- index = str.hashCode();
- index = str.hashCode();
- index = str.hashCode();
- index = str.hashCode();
- index = str.hashCode();
- index = str.hashCode();
- index = str.hashCode();
- index = str.hashCode();
- index = str.hashCode();
- }
- }
-
- /** replace()* */
-
- public void testStringreplace() {
- String rString;
- String str = STATIC_STRING_02;
- char c1 = ' ', c2 = ' ';
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = str.replace(c1, c2);
- rString = str.replace(c1, c2);
- rString = str.replace(c1, c2);
- rString = str.replace(c1, c2);
- rString = str.replace(c1, c2);
- rString = str.replace(c1, c2);
- rString = str.replace(c1, c2);
- rString = str.replace(c1, c2);
- rString = str.replace(c1, c2);
- rString = str.replace(c1, c2);
- }
- }
-
- public void testStringreplaceAll() {
- String rString;
- String str = STATIC_STRING_02, str1 = " ", str2 = "/";
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = str.replaceAll(str1, str2);
- rString = str.replaceAll(str1, str2);
- rString = str.replaceAll(str1, str2);
- rString = str.replaceAll(str1, str2);
- rString = str.replaceAll(str1, str2);
- rString = str.replaceAll(str1, str2);
- rString = str.replaceAll(str1, str2);
- rString = str.replaceAll(str1, str2);
- rString = str.replaceAll(str1, str2);
- rString = str.replaceAll(str1, str2);
- }
- }
-
- /** Convert a StringBuffer to a String* */
-
- public void testStringtoString() {
- StringBuffer sBuf = new StringBuffer(STATIC_STRING_02);
-
- String rString;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = sBuf.toString();
- rString = sBuf.toString();
- rString = sBuf.toString();
- rString = sBuf.toString();
- rString = sBuf.toString();
- rString = sBuf.toString();
- rString = sBuf.toString();
- rString = sBuf.toString();
- rString = sBuf.toString();
- rString = sBuf.toString();
- }
- }
-
- /** Split a string into an array of strings* */
-
- public void testStringsplit() {
- String[] strings;
- String str1 = STATIC_STRING_02, str = " ";
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- strings = str1.split(str);
- strings = str1.split(str);
- strings = str1.split(str);
- strings = str1.split(str);
- strings = str1.split(str);
- strings = str1.split(str);
- strings = str1.split(str);
- strings = str1.split(str);
- strings = str1.split(str);
- strings = str1.split(str);
-
- }
- }
-
- /** Split a string into an array of strings* */
-
- public void testStringsplit1() {
- String str = STATIC_STRING_02, str1 = " ";
- String[] strings;
- int pos = 8;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- strings = str.split(str1, pos);
- strings = str.split(str1, pos);
- strings = str.split(str1, pos);
- strings = str.split(str1, pos);
- strings = str.split(str1, pos);
- strings = str.split(str1, pos);
- strings = str.split(str1, pos);
- strings = str.split(str1, pos);
- strings = str.split(str1, pos);
- strings = str.split(str1, pos);
- }
- }
-
- public void testStringgetBytes() {
- byte[] bytes;
- String str = STATIC_STRING_02;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- bytes = str.getBytes();
- bytes = str.getBytes();
- bytes = str.getBytes();
- bytes = str.getBytes();
- bytes = str.getBytes();
- bytes = str.getBytes();
- bytes = str.getBytes();
- bytes = str.getBytes();
- bytes = str.getBytes();
- bytes = str.getBytes();
- }
- }
-
- /** copyValueOf(char[] data) * */
-
- public void testStringcopyValueOf() {
- String rString;
- char[] cArray = STATIC_CHAR_ARRAY;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = String.copyValueOf(cArray);
- rString = String.copyValueOf(cArray);
- rString = String.copyValueOf(cArray);
- rString = String.copyValueOf(cArray);
- rString = String.copyValueOf(cArray);
- rString = String.copyValueOf(cArray);
- rString = String.copyValueOf(cArray);
- rString = String.copyValueOf(cArray);
- rString = String.copyValueOf(cArray);
- rString = String.copyValueOf(cArray);
- }
- }
-
- /** copyValueOf(char[] data, int index, int count)* */
-
- public void testStringcopyValueOf1() {
- String rString;
- int start = 1, end = 7;
- char[] cArray = STATIC_CHAR_ARRAY;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = String.copyValueOf(cArray, start, end);
- rString = String.copyValueOf(cArray, start, end);
- rString = String.copyValueOf(cArray, start, end);
- rString = String.copyValueOf(cArray, start, end);
- rString = String.copyValueOf(cArray, start, end);
- rString = String.copyValueOf(cArray, start, end);
- rString = String.copyValueOf(cArray, start, end);
- rString = String.copyValueOf(cArray, start, end);
- rString = String.copyValueOf(cArray, start, end);
- rString = String.copyValueOf(cArray, start, end);
- }
- }
-
- /** trim()* */
-
- public void testStringtrim() {
- String mString =
- new String(
- " HELLO ANDROID ");
- String rString;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = mString.trim();
- rString = mString.trim();
- rString = mString.trim();
- rString = mString.trim();
- rString = mString.trim();
- rString = mString.trim();
- rString = mString.trim();
- rString = mString.trim();
- rString = mString.trim();
- rString = mString.trim();
- }
- }
-
- /** getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)* */
-
- public void testStringgetChars() {
- char[] cArray = STATIC_CHAR_ARRAY;
- String str = STATIC_STRING_01;
- int value1 = 7, value2 = 12, value3 = 1;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- str.getChars(value1, value2, cArray, value3);
- str.getChars(value1, value2, cArray, value3);
- str.getChars(value1, value2, cArray, value3);
- str.getChars(value1, value2, cArray, value3);
- str.getChars(value1, value2, cArray, value3);
- str.getChars(value1, value2, cArray, value3);
- str.getChars(value1, value2, cArray, value3);
- str.getChars(value1, value2, cArray, value3);
- str.getChars(value1, value2, cArray, value3);
- str.getChars(value1, value2, cArray, value3);
- }
- }
-
- /** toUpperCase()* */
-
- public void testStringtoUpperCase() {
- String rString, str = STATIC_STRING_02;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = str.toUpperCase();
- rString = str.toUpperCase();
- rString = str.toUpperCase();
- rString = str.toUpperCase();
- rString = str.toUpperCase();
- rString = str.toUpperCase();
- rString = str.toUpperCase();
- rString = str.toUpperCase();
- rString = str.toUpperCase();
- rString = str.toUpperCase();
- }
- }
-
- /** toUpperCase() with locale* */
-
- public void testStringtoUpperCase1() {
- Locale locale = new Locale("tr");
- String str = STATIC_STRING_02;
- String rString;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = str.toUpperCase(locale);
- rString = str.toUpperCase(locale);
- rString = str.toUpperCase(locale);
- rString = str.toUpperCase(locale);
- rString = str.toUpperCase(locale);
- rString = str.toUpperCase(locale);
- rString = str.toUpperCase(locale);
- rString = str.toUpperCase(locale);
- rString = str.toUpperCase(locale);
- rString = str.toUpperCase(locale);
- }
- }
-
- /** toLowerCase* */
-
- public void StringtoLowerCase() {
- String rString, str = STATIC_STRING_02;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = str.toLowerCase();
- rString = str.toLowerCase();
- rString = str.toLowerCase();
- rString = str.toLowerCase();
- rString = str.toLowerCase();
- rString = str.toLowerCase();
- rString = str.toLowerCase();
- rString = str.toLowerCase();
- rString = str.toLowerCase();
- rString = str.toLowerCase();
- }
- }
-
- /** toLowerCase with locale* */
-
- public void testStringtoLowerCase1() {
- Locale locale = new Locale("tr");
- String rString, str = STATIC_STRING_02;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = str.toLowerCase(locale);
- rString = str.toLowerCase(locale);
- rString = str.toLowerCase(locale);
- rString = str.toLowerCase(locale);
- rString = str.toLowerCase(locale);
- rString = str.toLowerCase(locale);
- rString = str.toLowerCase(locale);
- rString = str.toLowerCase(locale);
- rString = str.toLowerCase(locale);
- rString = str.toLowerCase(locale);
- }
- }
-
- /** charAt()* */
-
- public void testStringcharAt() {
- String str = STATIC_STRING_02;
- int index, pos = 21;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- index = str.charAt(pos);
- index = str.charAt(pos);
- index = str.charAt(pos);
- index = str.charAt(pos);
- index = str.charAt(pos);
- index = str.charAt(pos);
- index = str.charAt(pos);
- index = str.charAt(pos);
- index = str.charAt(pos);
- index = str.charAt(pos);
- }
- }
-
- public void testStringConcat() {
- String mString, str1 = STATIC_STRING_01, str2 = STATIC_STRING_02;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- mString = str1.concat(str2);
- mString = str1.concat(str2);
- mString = str1.concat(str2);
- mString = str1.concat(str2);
- mString = str1.concat(str2);
- mString = str1.concat(str2);
- mString = str1.concat(str2);
- mString = str1.concat(str2);
- mString = str1.concat(str2);
- mString = str1.concat(str2);
- }
- }
-
- public void testStringBufferAppend() {
- StringBuffer sBuf = new StringBuffer(" ");
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- sBuf.append(i);
- sBuf.append(i);
- sBuf.append(i);
- sBuf.append(i);
- sBuf.append(i);
- sBuf.append(i);
- sBuf.append(i);
- sBuf.append(i);
- sBuf.append(i);
- sBuf.append(i);
- }
- }
-
- public void testStringBufferInsert() {
- StringBuffer sBuf = new StringBuffer(" ");
- int index = sBuf.length();
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- sBuf.insert(index, i);
- sBuf.insert(index, i);
- sBuf.insert(index, i);
- sBuf.insert(index, i);
- sBuf.insert(index, i);
- sBuf.insert(index, i);
- sBuf.insert(index, i);
- sBuf.insert(index, i);
- sBuf.insert(index, i);
- sBuf.insert(index, i);
- }
- }
-
- public void testStringBufferReverse() {
- StringBuffer sBuf = STATIC_SBUF;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- sBuf.reverse();
- sBuf.reverse();
- sBuf.reverse();
- sBuf.reverse();
- sBuf.reverse();
- sBuf.reverse();
- sBuf.reverse();
- sBuf.reverse();
- sBuf.reverse();
- sBuf.reverse();
- }
- }
-
- public void testStringBufferSubstring() {
- StringBuffer sBuf = STATIC_SBUF;
- String rString;
- int index = 0;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = sBuf.substring(index);
- rString = sBuf.substring(index);
- rString = sBuf.substring(index);
- rString = sBuf.substring(index);
- rString = sBuf.substring(index);
- rString = sBuf.substring(index);
- rString = sBuf.substring(index);
- rString = sBuf.substring(index);
- rString = sBuf.substring(index);
- rString = sBuf.substring(index);
- }
- }
-
- public void testStringBufferSubstring1() {
- StringBuffer sBuf = STATIC_SBUF;
- String rString;
- int start = 5, end = 25;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- rString = sBuf.substring(start, end);
- rString = sBuf.substring(start, end);
- rString = sBuf.substring(start, end);
- rString = sBuf.substring(start, end);
- rString = sBuf.substring(start, end);
- rString = sBuf.substring(start, end);
- rString = sBuf.substring(start, end);
- rString = sBuf.substring(start, end);
- rString = sBuf.substring(start, end);
- rString = sBuf.substring(start, end);
- }
- }
-
- public void testStringBufferReplace() {
- StringBuffer sBuf = STATIC_SBUF;
- int start = 3, end = 6;
- String str = "ind";
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- sBuf.replace(start, end, str);
- sBuf.replace(start, end, str);
- sBuf.replace(start, end, str);
- sBuf.replace(start, end, str);
- sBuf.replace(start, end, str);
- sBuf.replace(start, end, str);
- sBuf.replace(start, end, str);
- sBuf.replace(start, end, str);
- sBuf.replace(start, end, str);
- sBuf.replace(start, end, str);
- }
- }
-
- public void testStringBufferIndexOf() {
- StringBuffer sBuf = STATIC_SBUF;
- String str = "t";
- int index;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- index = sBuf.indexOf(str);
- index = sBuf.indexOf(str);
- index = sBuf.indexOf(str);
- index = sBuf.indexOf(str);
- index = sBuf.indexOf(str);
- index = sBuf.indexOf(str);
- index = sBuf.indexOf(str);
- index = sBuf.indexOf(str);
- index = sBuf.indexOf(str);
- index = sBuf.indexOf(str);
- }
- }
-
- public void testStringBufferIndexOf1() {
- StringBuffer sBuf = STATIC_SBUF;
- String str = "tom";
- int index, pos = 12;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- index = sBuf.indexOf(str, pos);
- index = sBuf.indexOf(str, pos);
- index = sBuf.indexOf(str, pos);
- index = sBuf.indexOf(str, pos);
- index = sBuf.indexOf(str, pos);
- index = sBuf.indexOf(str, pos);
- index = sBuf.indexOf(str, pos);
- index = sBuf.indexOf(str, pos);
- index = sBuf.indexOf(str, pos);
- index = sBuf.indexOf(str, pos);
- }
-
- }
-
- public void testStringBufferLastIndexOf() {
- StringBuffer sBuf = STATIC_SBUF;
- String str = "t";
- int index;
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- index = sBuf.lastIndexOf(str);
- index = sBuf.lastIndexOf(str);
- index = sBuf.lastIndexOf(str);
- index = sBuf.lastIndexOf(str);
- index = sBuf.lastIndexOf(str);
- index = sBuf.lastIndexOf(str);
- index = sBuf.lastIndexOf(str);
- index = sBuf.lastIndexOf(str);
- index = sBuf.lastIndexOf(str);
- index = sBuf.lastIndexOf(str);
- }
- }
-
- public void testStringBufferLastIndexOf1() {
- StringBuffer sBuf = STATIC_SBUF;
- int index, pos = 36;
- String str = "tom";
- for (int i = ITERATIONS - 1; i >= 0; i--) {
- index = sBuf.lastIndexOf(str, pos);
- index = sBuf.lastIndexOf(str, pos);
- index = sBuf.lastIndexOf(str, pos);
- index = sBuf.lastIndexOf(str, pos);
- index = sBuf.lastIndexOf(str, pos);
- index = sBuf.lastIndexOf(str, pos);
- index = sBuf.lastIndexOf(str, pos);
- index = sBuf.lastIndexOf(str, pos);
- index = sBuf.lastIndexOf(str, pos);
- index = sBuf.lastIndexOf(str, pos);
- }
- }
-}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java b/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
index 0c2347d..716086b 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
@@ -16,14 +16,12 @@
package com.android.dumprendertree;
-import android.os.Handler;
import android.os.SystemClock;
import android.util.*;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.webkit.WebView;
-import java.lang.InterruptedException;
import java.util.Arrays;
import java.util.Vector;
@@ -33,7 +31,7 @@
WebViewEventSender(WebView webView) {
mWebView = webView;
- mTouchPoints = new Vector();
+ mTouchPoints = new Vector<TouchPoint>();
}
public void resetMouse() {
@@ -82,47 +80,23 @@
mouseUp();
}
- public void mouseDown() {
- /* KeyEvent event = new KeyEvent(
- KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
- mWebView.onKeyDown(event.getKeyCode(), event); */
- }
+ public void mouseDown() {
+ long ts = SystemClock.uptimeMillis();
+ MotionEvent event = MotionEvent.obtain(ts, ts, MotionEvent.ACTION_DOWN, mouseX, mouseY, 0);
+ mWebView.onTouchEvent(event);
+ }
- public void mouseMoveTo(int X, int Y) {
- if (X > mouseX) {
- KeyEvent event = new KeyEvent(
- KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT);
- mWebView.onKeyDown(event.getKeyCode(), event);
- mWebView.onKeyUp(event.getKeyCode(), event);
- } else if ( X < mouseX ) {
- KeyEvent event = new KeyEvent(
- KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT);
- mWebView.onKeyDown(event.getKeyCode(), event);
- mWebView.onKeyUp(event.getKeyCode(), event);
- }
- if (Y > mouseY) {
- KeyEvent event = new KeyEvent(
- KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN);
- mWebView.onKeyDown(event.getKeyCode(), event);
- mWebView.onKeyUp(event.getKeyCode(), event);
- } else if (Y < mouseY ) {
- KeyEvent event = new KeyEvent(
- KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP);
- mWebView.onKeyDown(event.getKeyCode(), event);
- mWebView.onKeyUp(event.getKeyCode(), event);
- }
- mouseX= X;
- mouseY= Y;
-
- }
+ public void mouseMoveTo(int X, int Y) {
+ mouseX= X;
+ mouseY= Y;
+ }
- public void mouseUp() {
- /* KeyEvent event = new KeyEvent(
- KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
- mWebView.onKeyDown(event.getKeyCode(), event);*/
+ public void mouseUp() {
+ long ts = SystemClock.uptimeMillis();
+ MotionEvent event = MotionEvent.obtain(ts, ts, MotionEvent.ACTION_UP, mouseX, mouseY, 0);
+ mWebView.onTouchEvent(event);
+ }
- }
-
// Assumes lowercase chars, case needs to be
// handled by calling function.
static int keyMapper(char c) {
@@ -365,7 +339,7 @@
mX = x;
mY = y;
}
- };
+ }
private Vector<TouchPoint> mTouchPoints;
private int mTouchMetaState;
diff --git a/tests/DumpRenderTree2/assets/run_apache2.py b/tests/DumpRenderTree2/assets/run_apache2.py
index f404090..5764f0e 100755
--- a/tests/DumpRenderTree2/assets/run_apache2.py
+++ b/tests/DumpRenderTree2/assets/run_apache2.py
@@ -33,7 +33,7 @@
else:
run_cmd = sys.argv[1]
- #Setup logging class
+ # Setup logging class
logging.basicConfig(level=logging.INFO, format='%(message)s')
if not run_cmd in ("start", "stop", "restart"):
@@ -41,55 +41,69 @@
logging.info("Usage: python run_apache2.py start|stop|restart")
return
- #Create /tmp/WebKit if it doesn't exist. This is needed for various files used by apache2
+ # Create /tmp/WebKit if it doesn't exist. This is needed for various files used by apache2
tmp_WebKit = os.path.join("/tmp", "WebKit")
if not os.path.exists(tmp_WebKit):
os.mkdir(tmp_WebKit)
- #Get the path to android tree root based on the script location.
- #Basically we go 5 levels up
+ # Get the path to android tree root based on the script location.
+ # Basically we go 5 levels up
parent = os.pardir
script_location = os.path.abspath(os.path.dirname(sys.argv[0]))
android_tree_root = os.path.join(script_location, parent, parent, parent, parent, parent)
android_tree_root = os.path.normpath(android_tree_root)
- #Prepare the command to set ${APACHE_RUN_USER} and ${APACHE_RUN_GROUP}
+ # Paths relative to android_tree_root
+ webkit_path = os.path.join("external", "webkit")
+ layout_tests_path = os.path.join(webkit_path, "LayoutTests")
+ http_conf_path = os.path.join(layout_tests_path, "http", "conf")
+
+ # Prepare the command to set ${APACHE_RUN_USER} and ${APACHE_RUN_GROUP}
envvars_path = os.path.join("/etc", "apache2", "envvars")
export_envvars_cmd = "source " + envvars_path
error_log_path = os.path.join(tmp_WebKit, "apache2-error.log")
+ custom_log_path = os.path.join(tmp_WebKit, "apache2-access.log")
- #Prepare the command to (re)start/stop the server with specified settings
+ # Prepare the command to (re)start/stop the server with specified settings
apache2_restart_cmd = "apache2 -k " + run_cmd
directives = " -c \"ServerRoot " + android_tree_root + "\""
- directives += " -c \"DocumentRoot " + os.path.join("external", "webkit") + "\""
- #This directive is commented out in apache2-debian-httpd.conf for some reason
- #However, it is useful to browse through tests in the browser, so it's added here.
- #One thing to note is that because of problems with mod_dir and port numbers, mod_dir
- #is turned off. That means that there _must_ be a trailing slash at the end of URL
- #for auto indexes to work correctly.
+ # We use http/tests as the document root as the HTTP tests use hardcoded
+ # resources at the server root. We then use aliases to make available the
+ # complete set of tests and the required scripts.
+ directives += " -c \"DocumentRoot " + os.path.join(layout_tests_path, "http", "tests/") + "\""
+ directives += " -c \"Alias /LayoutTests " + layout_tests_path + "\""
+ directives += " -c \"Alias /WebKitTools/DumpRenderTree/android " + \
+ os.path.join(webkit_path, "WebKitTools", "DumpRenderTree", "android") + "\""
+
+ # This directive is commented out in apache2-debian-httpd.conf for some reason
+ # However, it is useful to browse through tests in the browser, so it's added here.
+ # One thing to note is that because of problems with mod_dir and port numbers, mod_dir
+ # is turned off. That means that there _must_ be a trailing slash at the end of URL
+ # for auto indexes to work correctly.
directives += " -c \"LoadModule autoindex_module /usr/lib/apache2/modules/mod_autoindex.so\""
directives += " -c \"ErrorLog " + error_log_path +"\""
- directives += " -c \"SSLCertificateFile " + os.path.join ("external", "webkit", "LayoutTests",
- "http", "conf", "webkit-httpd.pem") + "\""
+ directives += " -c \"CustomLog " + custom_log_path + " combined\""
+ directives += " -c \"SSLCertificateFile " + os.path.join(http_conf_path, "webkit-httpd.pem") + \
+ "\""
directives += " -c \"User ${APACHE_RUN_USER}\""
directives += " -c \"Group ${APACHE_RUN_GROUP}\""
directives += " -C \"TypesConfig " + os.path.join("/etc", "mime.types") + "\""
- conf_file_cmd = " -f " + os.path.join(android_tree_root, "external", "webkit", "LayoutTests",
- "http", "conf", "apache2-debian-httpd.conf")
+ conf_file_cmd = " -f " + \
+ os.path.join(android_tree_root, http_conf_path, "apache2-debian-httpd.conf")
- #Try to execute the commands
+ # Try to execute the commands
logging.info("Will " + run_cmd + " apache2 server.")
cmd = export_envvars_cmd + " && " + apache2_restart_cmd + directives + conf_file_cmd
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, err) = p.communicate()
- #Output the stdout from the command to console
+ # Output the stdout from the command to console
logging.info(out)
- #Report any errors
+ # Report any errors
if p.returncode != 0:
logging.info("!! ERRORS:")
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AdditionalTextOutput.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AdditionalTextOutput.java
index 8fca629..bb9a916 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AdditionalTextOutput.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AdditionalTextOutput.java
@@ -63,7 +63,8 @@
port = url.getPort();
}
} catch (MalformedURLException e) {
- Log.e(LOG_TAG + "::appendDatabaseCallback", e.getMessage());
+ Log.e(LOG_TAG, "urlString=" + urlString + " databaseIdentifier=" + databaseIdentifier,
+ e);
}
output.append("UI DELEGATE DATABASE CALLBACK: ");
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/FileFilter.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/FileFilter.java
index cf82d24..bcc8564 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/FileFilter.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/FileFilter.java
@@ -124,9 +124,10 @@
}
}
} catch (FileNotFoundException e) {
- Log.w(LOG_TAG + "::reloadConfiguration", "File not found: " + txt_exp.getPath());
+ Log.w(LOG_TAG, "mRootDirPath=" + mRootDirPath + ": File not found: " +
+ txt_exp.getPath(), e);
} catch (IOException e) {
- Log.e(LOG_TAG + "::reloadConfiguration", "IOException: " + e.getMessage());
+ Log.e(LOG_TAG, "mRootDirPath=" + mRootDirPath, e);
}
}
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/FsUtils.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/FsUtils.java
index 212c187..0cfe69d 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/FsUtils.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/FsUtils.java
@@ -31,13 +31,13 @@
public static final String LOG_TAG = "FsUtils";
public static void writeDataToStorage(File file, byte[] bytes, boolean append) {
- Log.d(LOG_TAG + "::writeDataToStorage", file.getAbsolutePath());
+ Log.d(LOG_TAG, "writeDataToStorage(): " + file.getAbsolutePath());
try {
OutputStream outputStream = null;
try {
file.getParentFile().mkdirs();
file.createNewFile();
- Log.d(LOG_TAG + "::writeDataToStorage", "File created.");
+ Log.d(LOG_TAG, "writeDataToStorage(): File created.");
outputStream = new FileOutputStream(file, append);
outputStream.write(bytes);
} finally {
@@ -46,13 +46,13 @@
}
}
} catch (IOException e) {
- Log.e(LOG_TAG + "::writeDataToStorage", e.getMessage());
+ Log.e(LOG_TAG, "file.getAbsolutePath=" + file.getAbsolutePath(), e);
}
}
public static byte[] readDataFromStorage(File file) {
if (!file.exists()) {
- Log.d(LOG_TAG + "::readDataFromStorage", "File does not exist: "
+ Log.d(LOG_TAG, "readDataFromStorage(): File does not exist: "
+ file.getAbsolutePath());
return null;
}
@@ -70,7 +70,7 @@
}
}
} catch (IOException e) {
- Log.e(LOG_TAG + "::readDataFromStorage", e.getMessage());
+ Log.e(LOG_TAG, "file.getAbsolutePath=" + file.getAbsolutePath(), e);
}
return bytes;
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java
index 6db9571..7d57eb7 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java
@@ -56,7 +56,7 @@
}
public void clearAllDatabases() {
- Log.w(LOG_TAG + "::clearAllDatabases", "called");
+ Log.i(LOG_TAG, "clearAllDatabases() called");
WebStorage.getInstance().deleteAllData();
}
@@ -70,7 +70,7 @@
public void setDatabaseQuota(long quota) {
/** TODO: Reset this before every test! */
- Log.w(LOG_TAG + "::setDatabaseQuota", "called with: " + quota);
+ Log.i(LOG_TAG, "setDatabaseQuota() called with: " + quota);
WebStorage.getInstance().setQuotaForOrigin(Uri.fromFile(new File("")).toString(),
quota);
}
@@ -80,13 +80,13 @@
}
public void setMockGeolocationPosition(double latitude, double longitude, double accuracy) {
- Log.w(LOG_TAG + "::setMockGeolocationPosition", "latitude: " + latitude +
- " longitude: " + longitude + " accuracy: " + accuracy);
+ Log.i(LOG_TAG, "setMockGeolocationPosition(): " + "latitude=" + latitude +
+ " longitude=" + longitude + " accuracy=" + accuracy);
MockGeolocation.getInstance().setPosition(latitude, longitude, accuracy);
}
public void setMockGeolocationError(int code, String message) {
- Log.w(LOG_TAG + "::setMockGeolocationError", "code: " + code + " message: " + message);
+ Log.i(LOG_TAG, "setMockGeolocationError(): " + "code=" + code + " message=" + message);
MockGeolocation.getInstance().setError(code, message);
}
@@ -94,7 +94,10 @@
boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
// Configuration is in WebKit, so stay on WebCore thread, but go via LayoutTestsExecutor
// as we need access to the Webview.
+ Log.i(LOG_TAG, "setMockDeviceOrientation(" + canProvideAlpha +
+ ", " + alpha + ", " + canProvideBeta + ", " + beta + ", " + canProvideGamma +
+ ", " + gamma + ")");
mLayoutTestsExecutor.setMockDeviceOrientation(
canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma);
}
-}
+}
\ No newline at end of file
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
index 4737657..d17ec7c 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
@@ -112,7 +112,7 @@
private boolean mDumpDatabaseCallbacks;
private boolean mIsGeolocationPermissionSet;
private boolean mGeolocationPermission;
- private Map mPendingGeolocationPermissionCallbacks;
+ private Map<GeolocationPermissions.Callback, String> mPendingGeolocationPermissionCallbacks;
private EventSender mEventSender = new EventSender();
@@ -338,7 +338,7 @@
serviceMsg.setData(bundle);
mManagerServiceMessenger.send(serviceMsg);
} catch (RemoteException e) {
- Log.e(LOG_TAG + "::startTests", e.getMessage());
+ Log.e(LOG_TAG, "mCurrentTestRelativePath=" + mCurrentTestRelativePath, e);
}
runNextTest();
@@ -369,6 +369,7 @@
private void onTestTimedOut() {
assert mCurrentState.isRunningState() : "mCurrentState = " + mCurrentState.name();
+ Log.w(LOG_TAG, "onTestTimedOut(): " + mCurrentTestRelativePath);
mCurrentTestTimedOut = true;
/**
@@ -383,6 +384,7 @@
private void onTestFinished() {
assert mCurrentState.isRunningState() : "mCurrentState = " + mCurrentState.name();
+ Log.i(LOG_TAG, "onTestFinished(): " + mCurrentTestRelativePath);
obtainActualResultsFromWebView();
}
@@ -406,6 +408,7 @@
assert mCurrentState == CurrentState.OBTAINING_RESULT
: "mCurrentState = " + mCurrentState.name();
+ Log.i(LOG_TAG, "onActualResultsObtained(): " + mCurrentTestRelativePath);
mCurrentState = CurrentState.IDLE;
mResultHandler.removeMessages(MSG_TEST_TIMED_OUT);
@@ -436,7 +439,7 @@
serviceMsg.setData(bundle);
mManagerServiceMessenger.send(serviceMsg);
} catch (RemoteException e) {
- Log.e(LOG_TAG + "::reportResultToService", e.getMessage());
+ Log.e(LOG_TAG, "mCurrentTestRelativePath=" + mCurrentTestRelativePath, e);
}
}
@@ -455,7 +458,7 @@
Message.obtain(null, ManagerService.MSG_ALL_TESTS_FINISHED);
mManagerServiceMessenger.send(serviceMsg);
} catch (RemoteException e) {
- Log.e(LOG_TAG + "::onAllTestsFinished", e.getMessage());
+ Log.e(LOG_TAG, "mCurrentTestRelativePath=" + mCurrentTestRelativePath, e);
}
unbindService(mServiceConnection);
@@ -529,11 +532,11 @@
mGeolocationPermission = msg.arg1 == 1;
if (mPendingGeolocationPermissionCallbacks != null) {
- Iterator iter = mPendingGeolocationPermissionCallbacks.keySet().iterator();
+ Iterator<GeolocationPermissions.Callback> iter =
+ mPendingGeolocationPermissionCallbacks.keySet().iterator();
while (iter.hasNext()) {
- GeolocationPermissions.Callback callback =
- (GeolocationPermissions.Callback) iter.next();
- String origin = (String) mPendingGeolocationPermissionCallbacks.get(callback);
+ GeolocationPermissions.Callback callback = iter.next();
+ String origin = mPendingGeolocationPermissionCallbacks.get(callback);
callback.invoke(origin, mGeolocationPermission, false);
}
mPendingGeolocationPermissionCallbacks = null;
@@ -541,7 +544,7 @@
break;
default:
- Log.w(LOG_TAG + "::handleMessage", "Message code does not exist: " + msg.what);
+ assert false : "msg.what=" + msg.what;
break;
}
}
@@ -555,41 +558,42 @@
}
public void waitUntilDone() {
- Log.w(LOG_TAG + "::waitUntilDone", "called");
+ Log.i(LOG_TAG, mCurrentTestRelativePath + ": waitUntilDone() called");
mLayoutTestControllerHandler.sendEmptyMessage(MSG_WAIT_UNTIL_DONE);
}
public void notifyDone() {
- Log.w(LOG_TAG + "::notifyDone", "called");
+ Log.i(LOG_TAG, mCurrentTestRelativePath + ": notifyDone() called");
mLayoutTestControllerHandler.sendEmptyMessage(MSG_NOTIFY_DONE);
}
public void dumpAsText(boolean enablePixelTest) {
- Log.w(LOG_TAG + "::dumpAsText(" + enablePixelTest + ")", "called");
+ Log.i(LOG_TAG, mCurrentTestRelativePath + ": dumpAsText(" + enablePixelTest + ") called");
/** TODO: Implement */
if (enablePixelTest) {
- Log.w(LOG_TAG + "::dumpAsText", "enablePixelTest not implemented, switching to false");
+ Log.w(LOG_TAG, "enablePixelTest not implemented, switching to false");
}
mLayoutTestControllerHandler.sendEmptyMessage(MSG_DUMP_AS_TEXT);
}
public void dumpChildFramesAsText() {
- Log.w(LOG_TAG + "::dumpChildFramesAsText", "called");
+ Log.i(LOG_TAG, mCurrentTestRelativePath + ": dumpChildFramesAsText() called");
mLayoutTestControllerHandler.sendEmptyMessage(MSG_DUMP_CHILD_FRAMES_AS_TEXT);
}
public void setCanOpenWindows() {
- Log.w(LOG_TAG + "::setCanOpenWindows", "called");
+ Log.i(LOG_TAG, mCurrentTestRelativePath + ": setCanOpenWindows() called");
mLayoutTestControllerHandler.sendEmptyMessage(MSG_SET_CAN_OPEN_WINDOWS);
}
public void dumpDatabaseCallbacks() {
- Log.w(LOG_TAG + "::dumpDatabaseCallbacks:", "called");
+ Log.i(LOG_TAG, mCurrentTestRelativePath + ": dumpDatabaseCallbacks() called");
mLayoutTestControllerHandler.sendEmptyMessage(MSG_DUMP_DATABASE_CALLBACKS);
}
public void setGeolocationPermission(boolean allow) {
- Log.w(LOG_TAG + "::setGeolocationPermission", "called");
+ Log.i(LOG_TAG, mCurrentTestRelativePath + ": setGeolocationPermission(" + allow +
+ ") called");
Message msg = mLayoutTestControllerHandler.obtainMessage(MSG_SET_GEOLOCATION_PERMISSION);
msg.arg1 = allow ? 1 : 0;
msg.sendToTarget();
@@ -597,7 +601,10 @@
public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
+ Log.i(LOG_TAG, mCurrentTestRelativePath + ": setMockDeviceOrientation(" + canProvideAlpha +
+ ", " + alpha + ", " + canProvideBeta + ", " + beta + ", " + canProvideGamma +
+ ", " + gamma + ")");
mCurrentWebView.setMockDeviceOrientation(canProvideAlpha, alpha, canProvideBeta, beta,
canProvideGamma, gamma);
}
-}
+}
\ No newline at end of file
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java
index 31026d6..951126f 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java
@@ -88,7 +88,7 @@
break;
case MSG_PROCESS_ACTUAL_RESULTS:
- Log.d(LOG_TAG + ".mIncomingHandler", msg.getData().getString("relativePath"));
+ Log.d(LOG_TAG,"mIncomingHandler: " + msg.getData().getString("relativePath"));
onActualResultsObtained(msg.getData());
break;
@@ -151,11 +151,13 @@
AbstractResult results =
AbstractResult.TestType.valueOf(bundle.getString("type")).createResult(bundle);
+ Log.i(LOG_TAG, "onActualResultObtained: " + results.getRelativePath());
handleResults(results);
}
private void ensureNextTestSetup(String nextTest, int index) {
if (nextTest == null) {
+ Log.w(LOG_TAG, "ensureNextTestSetup(): nextTest=null");
return;
}
@@ -172,8 +174,8 @@
private void onTestCrashed() {
handleResults(new CrashedDummyResult(mCurrentlyRunningTest));
- Log.w(LOG_TAG + "::onTestCrashed", mCurrentlyRunningTest +
- "(" + mCurrentlyRunningTestIndex + ")");
+ Log.w(LOG_TAG, "onTestCrashed(): " + mCurrentlyRunningTest +
+ " (" + mCurrentlyRunningTestIndex + ")");
Intent intent = new Intent(this, TestsListActivity.class);
intent.setAction(Intent.ACTION_REBOOT);
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/VisualDiffUtils.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/VisualDiffUtils.java
index 250b6bc..26bf75c 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/VisualDiffUtils.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/VisualDiffUtils.java
@@ -204,4 +204,4 @@
}
return html.toString();
}
-}
+}
\ No newline at end of file
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/AdbUtils.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/AdbUtils.java
new file mode 100644
index 0000000..d165a1a
--- /dev/null
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/AdbUtils.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010 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.dumprendertree2.forwarder;
+
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * The utility class that can setup a socket allowing the device to communicate with remote
+ * machines through the machine that the device is connected to via adb.
+ */
+public class AdbUtils {
+ private static final String LOG_TAG = "AdbUtils";
+
+ private static final String ADB_OK = "OKAY";
+ private static final int ADB_PORT = 5037;
+ private static final String ADB_HOST = "127.0.0.1";
+ private static final int ADB_RESPONSE_SIZE = 4;
+
+ /**
+ * Send an ADB command using existing socket connection
+ *
+ * The streams provided must be from a socket connected to adb already
+ *
+ * @param is input stream of the socket connection
+ * @param os output stream of the socket
+ * @param cmd the adb command to send
+ * @return if adb gave a success response
+ * @throws IOException
+ */
+ private static boolean sendAdbCmd(InputStream is, OutputStream os, String cmd)
+ throws IOException {
+ byte[] buf = new byte[ADB_RESPONSE_SIZE];
+
+ cmd = String.format("%04X", cmd.length()) + cmd;
+ os.write(cmd.getBytes());
+ int read = is.read(buf);
+ if (read != ADB_RESPONSE_SIZE || !ADB_OK.equals(new String(buf))) {
+ Log.w(LOG_TAG, "adb cmd faild.");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Get a tcp socket connection to specified IP address and port proxied by adb
+ *
+ * The proxying is transparent, e.g. if a socket is returned, then it can be written to and
+ * read from as if it is directly connected to the target
+ *
+ * @param remoteAddress IP address of the host to connect to
+ * @param remotePort port of the host to connect to
+ * @return a valid Socket instance if successful, null otherwise
+ */
+ public static Socket getSocketToRemoteMachine(String remoteAddress, int remotePort) {
+ try {
+ Socket socket = new Socket(ADB_HOST, ADB_PORT);
+ String cmd = "tcp:" + remotePort + ":" + remoteAddress;
+ if (!sendAdbCmd(socket.getInputStream(), socket.getOutputStream(), cmd)) {
+ socket.close();
+ return null;
+ }
+ return socket;
+ } catch (IOException ioe) {
+ Log.w(LOG_TAG, "error creating adb socket", ioe);
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/ConnectionHandler.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/ConnectionHandler.java
new file mode 100644
index 0000000..6a6cb7f
--- /dev/null
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/ConnectionHandler.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2010 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.dumprendertree2.forwarder;
+
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * Worker class for {@link Forwarder}. A ConnectionHandler will be created once the Forwarder
+ * accepts an incoming connection, and it will then forward the incoming/outgoing streams to a
+ * connection already proxied by adb networking (see also {@link AdbUtils}).
+ */
+public class ConnectionHandler {
+
+ private static final String LOG_TAG = "ConnectionHandler";
+
+ private class SocketPipeThread extends Thread {
+
+ private Socket mInSocket, mOutSocket;
+
+ public SocketPipeThread(Socket inSocket, Socket outSocket) {
+ mInSocket = inSocket;
+ mOutSocket = outSocket;
+ }
+
+ @Override
+ public void run() {
+ InputStream is;
+ OutputStream os;
+ try {
+ synchronized (this) {
+ is = mInSocket.getInputStream();
+ os = mOutSocket.getOutputStream();
+ }
+ } catch (IOException e) {
+ Log.w(LOG_TAG, this.toString(), e);
+ return;
+ }
+
+ byte[] buffer = new byte[4096];
+ int length;
+ while (true) {
+ try {
+ synchronized (this) {
+ if ((length = is.read(buffer)) <= 0) {
+ break;
+ }
+ os.write(buffer, 0, length);
+ }
+ } catch (IOException e) {
+ /** This exception means one of the streams is closed */
+ Log.v(LOG_TAG, this.toString(), e);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SocketPipeThread:\n" + mInSocket + "\n=>\n" + mOutSocket;
+ }
+ }
+
+ private Socket mFromSocket, mToSocket;
+ private SocketPipeThread mFromToPipe, mToFromPipe;
+
+ public ConnectionHandler(Socket fromSocket, Socket toSocket) {
+ mFromSocket = fromSocket;
+ mToSocket = toSocket;
+ mFromToPipe = new SocketPipeThread(mFromSocket, mToSocket);
+ mToFromPipe = new SocketPipeThread(mToSocket, mFromSocket);
+ }
+
+ public void start() {
+ mFromToPipe.start();
+ mToFromPipe.start();
+ }
+
+ public void stop() {
+ shutdown(mFromSocket);
+ shutdown(mToSocket);
+ }
+
+ private void shutdown(Socket socket) {
+ try {
+ synchronized (mFromToPipe) {
+ synchronized (mToFromPipe) {
+ /** This will stop the while loop in the run method */
+ socket.shutdownInput();
+ socket.shutdownOutput();
+ socket.close();
+ }
+ }
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "mFromToPipe=" + mFromToPipe + " mToFromPipe=" + mToFromPipe, e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/Forwarder.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/Forwarder.java
new file mode 100644
index 0000000..e5ef6da
--- /dev/null
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/Forwarder.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2010 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.dumprendertree2.forwarder;
+
+import android.util.Log;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A port forwarding server. Listens on localhost on specified port and forwards the tcp
+ * communications to external socket via adb networking proxy.
+ */
+public class Forwarder extends Thread {
+ private static final String LOG_TAG = "Forwarder";
+
+ private int mPort;
+ private String mRemoteMachineIpAddress;
+
+ private Boolean mIsRunning = false;
+ private ServerSocket mServerSocket;
+
+ private Set<ConnectionHandler> mConnectionHandlers = new HashSet<ConnectionHandler>();
+
+ public Forwarder(int port, String remoteMachineIpAddress) {
+ mPort = port;
+ mRemoteMachineIpAddress = remoteMachineIpAddress;
+ }
+
+ @Override
+ public void start() {
+ Log.i(LOG_TAG, "start(): Starting fowarder on port: " + mPort);
+ synchronized (this) {
+ if (mIsRunning) {
+ Log.w(LOG_TAG, "start(): Forwarder on port: " + mPort + " already running! NOOP.");
+ return;
+ }
+ }
+
+ try {
+ mServerSocket = new ServerSocket(mPort);
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "mPort=" + mPort, e);
+ return;
+ }
+
+ mIsRunning = true;
+ super.start();
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ synchronized (this) {
+ if (!mIsRunning) {
+ return;
+ }
+
+ /** These sockets will be closed when Forwarder.stop() is called */
+ Socket localSocket;
+ Socket remoteSocket;
+ try {
+ localSocket = mServerSocket.accept();
+ remoteSocket = AdbUtils.getSocketToRemoteMachine(mRemoteMachineIpAddress,
+ mPort);
+ } catch (IOException e) {
+ /** This most likely means that mServerSocket is already closed */
+ Log.w(LOG_TAG + "mPort=" + mPort, e);
+ return;
+ }
+
+ if (remoteSocket == null) {
+ try {
+ localSocket.close();
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "mPort=" + mPort, e);
+ }
+
+ Log.e(LOG_TAG, "run(): mPort= " + mPort + " Failed to start forwarding from " +
+ localSocket);
+ continue;
+ }
+
+ ConnectionHandler forwarder = new ConnectionHandler(localSocket, remoteSocket);
+ mConnectionHandlers.add(forwarder);
+ forwarder.start();
+
+ }
+ }
+ }
+
+ public void finish() {
+ synchronized (this) {
+ if (!mIsRunning) {
+ return;
+ }
+ }
+
+ try {
+ mServerSocket.close();
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "mPort=" + mPort, e);
+ }
+
+ synchronized (this) {
+ mIsRunning = false;
+ }
+
+ for (ConnectionHandler connectionHandler : mConnectionHandlers) {
+ connectionHandler.stop();
+ }
+ mConnectionHandlers.clear();
+ }
+}
\ No newline at end of file
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/ForwarderManager.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/ForwarderManager.java
new file mode 100644
index 0000000..10fee4b
--- /dev/null
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/ForwarderManager.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 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.dumprendertree2.forwarder;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A simple class to start and stop Forwarders running on some ports.
+ *
+ * It uses a singleton pattern and is thread safe.
+ */
+public class ForwarderManager {
+ /**
+ * The IP address of the server serving the tests.
+ */
+ private static final String HOST_IP = "127.0.0.1";
+
+ /**
+ * We use these ports because other webkit platforms do. They are set up in
+ * external/webkit/LayoutTests/http/conf/apache2-debian-httpd.conf
+ */
+ public static final int HTTP_PORT = 8080;
+ public static final int HTTPS_PORT = 8443;
+
+ private static ForwarderManager forwarderManager;
+
+ private Set<Forwarder> mServers;
+
+ private ForwarderManager() {
+ mServers = new HashSet<Forwarder>(2);
+ mServers.add(new Forwarder(HTTP_PORT, HOST_IP));
+ mServers.add(new Forwarder(HTTPS_PORT, HOST_IP));
+ }
+
+ public static synchronized ForwarderManager getForwarderManager() {
+ if (forwarderManager == null) {
+ forwarderManager = new ForwarderManager();
+ }
+ return forwarderManager;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ throw new CloneNotSupportedException();
+ }
+
+ public synchronized void start() {
+ for (Forwarder server : mServers) {
+ server.start();
+ }
+ }
+
+ public synchronized void stop() {
+ for (Forwarder server : mServers) {
+ server.finish();
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/scriptsupport/Starter.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/scriptsupport/Starter.java
index ddfae69..e730c8a 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/scriptsupport/Starter.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/scriptsupport/Starter.java
@@ -66,7 +66,7 @@
try {
this.wait();
} catch (InterruptedException e) {
- Log.e(LOG_TAG + "::startLayoutTests", e.getMessage());
+ Log.e(LOG_TAG, "startLayoutTests()", e);
}
}
}
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index abccf9b..b50a393 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -141,9 +141,9 @@
if (bundle->getVerbose()) {
printf("Archive: %s\n", zipFileName);
printf(
- " Length Method Size Ratio Date Time CRC-32 Name\n");
+ " Length Method Size Ratio Offset Date Time CRC-32 Name\n");
printf(
- "-------- ------ ------- ----- ---- ---- ------ ----\n");
+ "-------- ------ ------- ----- ------- ---- ---- ------ ----\n");
}
totalUncLen = totalCompLen = 0;
@@ -159,12 +159,13 @@
strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M",
localtime(&when));
- printf("%8ld %-7.7s %7ld %3d%% %s %08lx %s\n",
+ printf("%8ld %-7.7s %7ld %3d%% %8zd %s %08lx %s\n",
(long) entry->getUncompressedLen(),
compressionName(entry->getCompressionMethod()),
(long) entry->getCompressedLen(),
calcPercent(entry->getUncompressedLen(),
entry->getCompressedLen()),
+ (size_t) entry->getLFHOffset(),
dateBuf,
entry->getCRC32(),
entry->getFileName());
diff --git a/tools/aapt/ZipEntry.h b/tools/aapt/ZipEntry.h
index 7f721b4..c2f3227 100644
--- a/tools/aapt/ZipEntry.h
+++ b/tools/aapt/ZipEntry.h
@@ -72,6 +72,11 @@
off_t getCompressedLen(void) const { return mCDE.mCompressedSize; }
/*
+ * Return the offset of the local file header.
+ */
+ off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; }
+
+ /*
* Return the absolute file offset of the start of the compressed or
* uncompressed data.
*/
@@ -186,11 +191,6 @@
void setModWhen(time_t when);
/*
- * Return the offset of the local file header.
- */
- off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; }
-
- /*
* Set the offset of the local file header, relative to the start of
* the current file.
*/
diff --git a/voip/java/android/net/sip/SipProfile.java b/voip/java/android/net/sip/SipProfile.java
index e71c293..6c99141 100644
--- a/voip/java/android/net/sip/SipProfile.java
+++ b/voip/java/android/net/sip/SipProfile.java
@@ -35,7 +35,7 @@
* Class containing a SIP account, domain and server information.
* @hide
*/
-public class SipProfile implements Parcelable, Serializable {
+public class SipProfile implements Parcelable, Serializable, Cloneable {
private static final long serialVersionUID = 1L;
private static final int DEFAULT_PORT = 5060;
private Address mAddress;
@@ -46,6 +46,8 @@
private String mProfileName;
private boolean mSendKeepAlive = false;
private boolean mAutoRegistration = true;
+ private boolean mAllowOutgoingCall = false;
+ private int mCallingUid = -1;
/** @hide */
public static final Parcelable.Creator<SipProfile> CREATOR =
@@ -79,6 +81,23 @@
}
/**
+ * Creates a builder based on the given profile.
+ */
+ public Builder(SipProfile profile) {
+ if (profile == null) throw new NullPointerException();
+ try {
+ mProfile = (SipProfile) profile.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException("should not occur", e);
+ }
+ mProfile.mAddress = null;
+ mUri = profile.getUri();
+ mUri.setUserPassword(profile.getPassword());
+ mDisplayName = profile.getDisplayName();
+ mProxyAddress = profile.getProxyAddress();
+ }
+
+ /**
* Constructor.
*
* @param uriString the URI string as "sip:<user_name>@<domain>"
@@ -226,6 +245,18 @@
}
/**
+ * Sets the allow-outgoing-call flag.
+ *
+ * @param flag true if allowing to make outgoing call on the profile;
+ * false otherwise
+ * @return this builder object
+ */
+ public Builder setOutgoingCallAllowed(boolean flag) {
+ mProfile.mAllowOutgoingCall = flag;
+ return this;
+ }
+
+ /**
* Builds and returns the SIP profile object.
*
* @return the profile object created
@@ -262,6 +293,8 @@
mProfileName = in.readString();
mSendKeepAlive = (in.readInt() == 0) ? false : true;
mAutoRegistration = (in.readInt() == 0) ? false : true;
+ mAllowOutgoingCall = (in.readInt() == 0) ? false : true;
+ mCallingUid = in.readInt();
}
/** @hide */
@@ -274,6 +307,8 @@
out.writeString(mProfileName);
out.writeInt(mSendKeepAlive ? 1 : 0);
out.writeInt(mAutoRegistration ? 1 : 0);
+ out.writeInt(mAllowOutgoingCall ? 1 : 0);
+ out.writeInt(mCallingUid);
}
/** @hide */
@@ -398,4 +433,27 @@
public boolean getAutoRegistration() {
return mAutoRegistration;
}
+
+ /**
+ * Returns true if allowing to make outgoing calls on this profile.
+ */
+ public boolean isOutgoingCallAllowed() {
+ return mAllowOutgoingCall;
+ }
+
+ /**
+ * Sets the calling process's Uid in the sip service.
+ * @hide
+ */
+ public void setCallingUid(int uid) {
+ mCallingUid = uid;
+ }
+
+ /**
+ * Gets the calling process's Uid in the sip settings.
+ * @hide
+ */
+ public int getCallingUid() {
+ return mCallingUid;
+ }
}
diff --git a/voip/jni/rtp/Android.mk b/voip/jni/rtp/Android.mk
index 3bd85aa..a364355 100644
--- a/voip/jni/rtp/Android.mk
+++ b/voip/jni/rtp/Android.mk
@@ -32,11 +32,10 @@
libutils \
libmedia
-LOCAL_STATIC_LIBRARIES := libspeex
+LOCAL_STATIC_LIBRARIES :=
LOCAL_C_INCLUDES += \
- $(JNI_H_INCLUDE) \
- external/speex/include
+ $(JNI_H_INCLUDE)
LOCAL_CFLAGS += -fvisibility=hidden
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index b5a4e22..bb45a9a 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -40,8 +40,6 @@
#include <media/AudioTrack.h>
#include <media/mediarecorder.h>
-#include <speex/speex_echo.h>
-
#include "jni.h"
#include "JNIHelp.h"
@@ -447,8 +445,6 @@
int mDeviceSocket;
AudioTrack mTrack;
AudioRecord mRecord;
-
- SpeexEchoState *mEchoState;
bool networkLoop();
bool deviceLoop();
@@ -510,7 +506,6 @@
mEventQueue = -1;
mDtmfEvent = -1;
mDeviceSocket = -1;
- mEchoState = NULL;
mNetworkThread = new NetworkThread(this);
mDeviceThread = new DeviceThread(this);
}
@@ -523,9 +518,6 @@
mRecord.stop();
close(mEventQueue);
close(mDeviceSocket);
- if (mEchoState) {
- speex_echo_state_destroy(mEchoState);
- }
while (mChain) {
AudioStream *next = mChain->mNext;
delete mChain;
@@ -574,8 +566,7 @@
}
LOGD("latency: output %d, input %d", mTrack.latency(), mRecord.latency());
- // Initialize echo canceller.
- mEchoState = speex_echo_state_init(sampleCount, sampleRate);
+ // TODO: initialize echo canceler here.
// Create device socket.
int pair[2];
@@ -642,7 +633,6 @@
if (mode == MUTED) {
mRecord.stop();
} else {
- speex_echo_state_reset(mEchoState);
mRecord.start();
}
@@ -803,7 +793,7 @@
status_t status = mRecord.obtainBuffer(&buffer, 1);
if (status == NO_ERROR) {
- int count = ((int)buffer.frameCount < toRead) ?
+ int count = (buffer.frameCount < toRead) ?
buffer.frameCount : toRead;
memcpy(&input[mSampleCount - toRead], buffer.i8, count * 2);
toRead -= count;
@@ -827,9 +817,8 @@
if (mMode == NORMAL) {
send(mDeviceSocket, input, sizeof(input), MSG_DONTWAIT);
} else {
- int16_t result[mSampleCount];
- speex_echo_cancellation(mEchoState, input, output, result);
- send(mDeviceSocket, result, sizeof(result), MSG_DONTWAIT);
+ // TODO: Echo canceller runs here.
+ send(mDeviceSocket, input, sizeof(input), MSG_DONTWAIT);
}
}
return true;
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 5734953..492f69c 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -736,7 +736,11 @@
}
public void connectNetwork(WifiConfiguration wifiConfig) {
- sendMessage(obtainMessage(CMD_CONNECT_NETWORK, wifiConfig));
+ /* arg1 is used to indicate netId, force a netId value of -1 when
+ * we are passing a configuration since the default value of
+ * 0 is a valid netId
+ */
+ sendMessage(obtainMessage(CMD_CONNECT_NETWORK, -1, 0, wifiConfig));
}
public void saveNetwork(WifiConfiguration wifiConfig) {
@@ -1469,16 +1473,13 @@
}
private void enableAllNetworks() {
- if (mEnableAllNetworks) {
- mEnableAllNetworks = false;
- for (WifiConfiguration config : mConfiguredNetworks) {
- if(config != null && config.status == Status.DISABLED) {
- WifiNative.enableNetworkCommand(config.networkId, false);
- }
+ for (WifiConfiguration config : mConfiguredNetworks) {
+ if(config != null && config.status == Status.DISABLED) {
+ WifiNative.enableNetworkCommand(config.networkId, false);
}
- WifiNative.saveConfigCommand();
- updateConfigAndSendChangeBroadcast();
}
+ WifiNative.saveConfigCommand();
+ updateConfigAndSendChangeBroadcast();
}
private int addOrUpdateNetworkNative(WifiConfiguration config) {
@@ -2404,7 +2405,8 @@
mWifiInfo.setMacAddress(WifiNative.getMacAddressCommand());
- updateConfigAndSendChangeBroadcast();
+ updateConfiguredNetworks();
+ enableAllNetworks();
//TODO: initialize and fix multicast filtering
//mWM.initializeMulticastFiltering();
@@ -2875,15 +2877,25 @@
addOrUpdateNetworkNative(config);
WifiNative.saveConfigCommand();
- // Connect to network by disabling others.
+ /* We connect to a specific network by first enabling that network
+ * and disabling all other networks in the supplicant. Disabling a
+ * connected network will cause a disconnection from the network.
+ * A reconnectCommand() will then initiate a connection to the enabled
+ * network.
+ */
WifiNative.enableNetworkCommand(netId, true);
- WifiNative.reconnectCommand();
+ /* Save a flag to indicate that we need to enable all
+ * networks after supplicant indicates a network
+ * state change event
+ */
mEnableAllNetworks = true;
+ WifiNative.reconnectCommand();
/* update the configured networks but not send a
* broadcast to avoid a fetch from settings
* during this temporary disabling of networks
*/
updateConfiguredNetworks();
+ transitionTo(mDisconnectingState);
break;
case SCAN_RESULTS_EVENT:
/* Set the scan setting back to "connect" mode */
@@ -2899,16 +2911,13 @@
mWifiInfo.setBSSID(mLastBssid = stateChangeResult.BSSID);
mWifiInfo.setNetworkId(stateChangeResult.networkId);
mLastNetworkId = stateChangeResult.networkId;
- enableAllNetworks();
/* send event to CM & network change broadcast */
setDetailedState(DetailedState.OBTAINING_IPADDR);
sendNetworkStateChangeBroadcast(mLastBssid);
-
transitionTo(mConnectingState);
break;
case NETWORK_DISCONNECTION_EVENT:
Log.d(TAG,"Network connection lost");
- enableAllNetworks();
handleNetworkDisconnect();
transitionTo(mDisconnectedState);
break;
@@ -3057,6 +3066,13 @@
WifiNative.disconnectCommand();
transitionTo(mDisconnectingState);
break;
+ /* Ignore connection to same network */
+ case CMD_CONNECT_NETWORK:
+ int netId = message.arg1;
+ if (mWifiInfo.getNetworkId() == netId) {
+ break;
+ }
+ return NOT_HANDLED;
/* Ignore */
case NETWORK_CONNECTION_EVENT:
break;
@@ -3127,6 +3143,13 @@
deferMessage(message);
}
break;
+ /* Ignore connection to same network */
+ case CMD_CONNECT_NETWORK:
+ int netId = message.arg1;
+ if (mWifiInfo.getNetworkId() == netId) {
+ break;
+ }
+ return NOT_HANDLED;
/* Ignore */
case NETWORK_CONNECTION_EVENT:
break;
@@ -3162,6 +3185,13 @@
EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
return HANDLED;
}
+ @Override
+ public void exit() {
+ if (mEnableAllNetworks) {
+ mEnableAllNetworks = false;
+ enableAllNetworks();
+ }
+ }
}
class DisconnectedState extends HierarchicalState {