Merge "Use only one GL context per process, share chaches."
diff --git a/Android.mk b/Android.mk
index a73767b..7c848c6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -123,10 +123,6 @@
core/java/android/net/IThrottleManager.aidl \
core/java/android/os/IHardwareService.aidl \
core/java/android/os/IMessenger.aidl \
- core/java/android/os/storage/IMountService.aidl \
- core/java/android/os/storage/IMountServiceListener.aidl \
- core/java/android/os/storage/IMountShutdownObserver.aidl \
- core/java/android/os/storage/IObbActionListener.aidl \
core/java/android/os/INetworkManagementService.aidl \
core/java/android/os/INetStatService.aidl \
core/java/android/os/IPermissionController.aidl \
@@ -383,8 +379,6 @@
# (see development/build/sdk.atree)
web_docs_sample_code_flags := \
-hdf android.hasSamples 1 \
- -samplecode $(sample_dir)/AccessibilityService \
- resources/samples/AccessibilityService "Accessibility Service" \
-samplecode $(sample_dir)/ApiDemos \
resources/samples/ApiDemos "API Demos" \
-samplecode $(sample_dir)/BackupRestore \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index f73e4d5..a9f4d19 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -76,6 +76,7 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/lib/libhwui.so)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/symbols/system/lib/libhwui.so)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libhwui.so)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/storage/*)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/api/current.xml b/api/current.xml
index d935c38..cbbf3d1 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -6708,6 +6708,17 @@
visibility="public"
>
</field>
+<field name="listChoiceBackgroundIndicator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843568"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="listChoiceIndicatorMultiple"
type="int"
transient="false"
@@ -15715,6 +15726,17 @@
visibility="public"
>
</field>
+<field name="simple_selectable_list_item"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367074"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="simple_spinner_dropdown_item"
type="int"
transient="false"
@@ -16663,7 +16685,7 @@
visibility="public"
>
</field>
-<field name="Theme_Holo_NoTitleBar"
+<field name="Theme_Holo_NoActionBar"
type="int"
transient="false"
volatile="false"
@@ -16674,7 +16696,7 @@
visibility="public"
>
</field>
-<field name="Theme_Holo_NoTitleBar_Fullscreen"
+<field name="Theme_Holo_NoActionBar_Fullscreen"
type="int"
transient="false"
volatile="false"
@@ -16718,7 +16740,7 @@
visibility="public"
>
</field>
-<field name="Theme_Light_Holo_NoTitleBar"
+<field name="Theme_Light_Holo_NoActionBar"
type="int"
transient="false"
volatile="false"
@@ -16729,7 +16751,7 @@
visibility="public"
>
</field>
-<field name="Theme_Light_Holo_NoTitleBar_Fullscreen"
+<field name="Theme_Light_Holo_NoActionBar_Fullscreen"
type="int"
transient="false"
volatile="false"
@@ -19779,6 +19801,8 @@
deprecated="not deprecated"
visibility="public"
>
+<implements name="java.lang.Cloneable">
+</implements>
<constructor name="Animatable"
type="android.animation.Animatable"
static="false"
@@ -19811,6 +19835,19 @@
visibility="public"
>
</method>
+<method name="clone"
+ return="android.animation.Animatable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="CloneNotSupportedException" type="java.lang.CloneNotSupportedException">
+</exception>
+</method>
<method name="end"
return="void"
abstract="false"
@@ -20080,6 +20117,17 @@
visibility="public"
>
</method>
+<method name="getDuration"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getFrameDelay"
return="long"
abstract="false"
@@ -20091,6 +20139,17 @@
visibility="public"
>
</method>
+<method name="getInterpolator"
+ return="android.view.animation.Interpolator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getRepeatCount"
return="int"
abstract="false"
@@ -62851,6 +62910,42 @@
<parameter name="table" type="java.lang.String">
</parameter>
</method>
+<method name="queryNumEntries"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="db" type="android.database.sqlite.SQLiteDatabase">
+</parameter>
+<parameter name="table" type="java.lang.String">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+</method>
+<method name="queryNumEntries"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="db" type="android.database.sqlite.SQLiteDatabase">
+</parameter>
+<parameter name="table" type="java.lang.String">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+</method>
<method name="readExceptionFromParcel"
return="void"
abstract="false"
@@ -84570,6 +84665,17 @@
visibility="public"
>
</field>
+<field name="TYPE_GRAVITY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="TYPE_GYROSCOPE"
type="int"
transient="false"
@@ -84592,6 +84698,17 @@
visibility="public"
>
</field>
+<field name="TYPE_LINEAR_ACCELERATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="TYPE_MAGNETIC_FIELD"
type="int"
transient="false"
@@ -84636,6 +84753,17 @@
visibility="public"
>
</field>
+<field name="TYPE_ROTATION_VECTOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="11"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="TYPE_TEMPERATURE"
type="int"
transient="false"
@@ -84795,6 +84923,23 @@
<parameter name="p" type="float">
</parameter>
</method>
+<method name="getAngleChange"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="angleChange" type="float[]">
+</parameter>
+<parameter name="R" type="float[]">
+</parameter>
+<parameter name="prevR" type="float[]">
+</parameter>
+</method>
<method name="getDefaultSensor"
return="android.hardware.Sensor"
abstract="false"
@@ -84836,6 +84981,21 @@
<parameter name="values" type="float[]">
</parameter>
</method>
+<method name="getQuaternionFromVector"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="Q" type="float[]">
+</parameter>
+<parameter name="rv" type="float[]">
+</parameter>
+</method>
<method name="getRotationMatrix"
return="boolean"
abstract="false"
@@ -84855,6 +85015,21 @@
<parameter name="geomagnetic" type="float[]">
</parameter>
</method>
+<method name="getRotationMatrixFromVector"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="R" type="float[]">
+</parameter>
+<parameter name="rotationVector" type="float[]">
+</parameter>
+</method>
<method name="getSensorList"
return="java.util.List<android.hardware.Sensor>"
abstract="false"
@@ -136194,7 +136369,7 @@
deprecated="not deprecated"
visibility="public"
>
-<method name="getThreadBlockingPolicy"
+<method name="allowThreadDiskReads"
return="int"
abstract="false"
native="false"
@@ -136205,7 +136380,29 @@
visibility="public"
>
</method>
-<method name="setThreadBlockingPolicy"
+<method name="allowThreadDiskWrites"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getThreadPolicy"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setThreadPolicy"
return="void"
abstract="false"
native="false"
@@ -234473,7 +234670,9 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="offset" type="int">
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
</parameter>
</method>
<field name="FADE_OUT_DURATION"
@@ -258044,7 +258243,7 @@
<method name="copySign"
return="double"
abstract="false"
- native="true"
+ native="false"
synchronized="false"
static="true"
final="false"
@@ -258059,7 +258258,7 @@
<method name="copySign"
return="float"
abstract="false"
- native="true"
+ native="false"
synchronized="false"
static="true"
final="false"
@@ -269479,7 +269678,7 @@
>
<parameter name="numBits" type="int">
</parameter>
-<parameter name="rnd" type="java.util.Random">
+<parameter name="random" type="java.util.Random">
</parameter>
</constructor>
<constructor name="BigInteger"
@@ -269493,7 +269692,7 @@
</parameter>
<parameter name="certainty" type="int">
</parameter>
-<parameter name="rnd" type="java.util.Random">
+<parameter name="unused" type="java.util.Random">
</parameter>
</constructor>
<constructor name="BigInteger"
@@ -269503,7 +269702,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.lang.String">
+<parameter name="value" type="java.lang.String">
</parameter>
</constructor>
<constructor name="BigInteger"
@@ -269513,7 +269712,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.lang.String">
+<parameter name="value" type="java.lang.String">
</parameter>
<parameter name="radix" type="int">
</parameter>
@@ -269537,7 +269736,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="byte[]">
+<parameter name="value" type="byte[]">
</parameter>
</constructor>
<method name="abs"
@@ -269561,7 +269760,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.math.BigInteger">
+<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="and"
@@ -269574,7 +269773,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.math.BigInteger">
+<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="andNot"
@@ -269587,7 +269786,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.math.BigInteger">
+<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="bitCount"
@@ -269635,7 +269834,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.math.BigInteger">
+<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="divide"
@@ -269709,7 +269908,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.math.BigInteger">
+<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="getLowestSetBit"
@@ -269768,7 +269967,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.math.BigInteger">
+<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="min"
@@ -269781,7 +269980,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.math.BigInteger">
+<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="mod"
@@ -269835,7 +270034,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.math.BigInteger">
+<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="negate"
@@ -269881,7 +270080,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.math.BigInteger">
+<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="pow"
@@ -269909,7 +270108,7 @@
>
<parameter name="bitLength" type="int">
</parameter>
-<parameter name="rnd" type="java.util.Random">
+<parameter name="unused" type="java.util.Random">
</parameter>
</method>
<method name="remainder"
@@ -269985,7 +270184,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.math.BigInteger">
+<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<method name="testBit"
@@ -270035,7 +270234,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="long">
+<parameter name="value" type="long">
</parameter>
</method>
<method name="xor"
@@ -270048,7 +270247,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="val" type="java.math.BigInteger">
+<parameter name="value" type="java.math.BigInteger">
</parameter>
</method>
<field name="ONE"
@@ -276495,6 +276694,19 @@
<parameter name="p" type="java.security.Permission">
</parameter>
</method>
+<method name="isValidIP6Address"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ipAddress" type="java.lang.String">
+</parameter>
+</method>
</class>
<class name="SocketTimeoutException"
extends="java.io.InterruptedIOException"
diff --git a/core/java/android/animation/Animatable.java b/core/java/android/animation/Animatable.java
index 68415f0..a49ca8f 100644
--- a/core/java/android/animation/Animatable.java
+++ b/core/java/android/animation/Animatable.java
@@ -22,7 +22,7 @@
* This is the superclass for classes which provide basic support for animations which can be
* started, ended, and have <code>AnimatableListeners</code> added to them.
*/
-public abstract class Animatable {
+public abstract class Animatable implements Cloneable {
/**
@@ -107,6 +107,20 @@
}
}
+ @Override
+ public Animatable clone() throws CloneNotSupportedException {
+ final Animatable anim = (Animatable) super.clone();
+ if (mListeners != null) {
+ ArrayList<AnimatableListener> oldListeners = mListeners;
+ anim.mListeners = new ArrayList<AnimatableListener>();
+ int numListeners = oldListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ anim.mListeners.add(oldListeners.get(i));
+ }
+ }
+ return anim;
+ }
+
/**
* <p>An animation listener receives notifications from an animation.
* Notifications indicate animation related events, such as the end or the
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 951d104..eca5f0d 100755
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -19,6 +19,7 @@
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;
@@ -79,9 +80,11 @@
/**
* 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
+ * to clone() to make deep copies of them.
*/
-
// The first time that the animation's animateFrame() method is called. This time is used to
// determine elapsed time (and therefore the elapsed fraction) in subsequent calls
// to animateFrame()
@@ -197,15 +200,13 @@
/**
* The property/value sets being animated.
*/
- HashMap<String, PropertyValuesHolder> mValues;
+ PropertyValuesHolder[] mValues;
/**
- * This value is used in the simple/common case of animating just one value; the user
- * may call getAnimatedValue(), which should return the value of the first (and only)
- * ProeprtyValuesHolder animated value, which is looked up using this string.
+ * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values
+ * by property name during calls to getAnimatedValue(String).
*/
- String mFirstPropertyName;
-
+ HashMap<String, PropertyValuesHolder> mValuesMap;
/**
* The type of the values, as determined by the valueFrom/valueTo properties.
@@ -290,11 +291,11 @@
break;
}
- mValues = new HashMap<String, PropertyValuesHolder>(1);
- mFirstPropertyName = "";
- PropertyValuesHolder valuesHolder = new PropertyValuesHolder(mFirstPropertyName,
- valueFrom, valueTo);
- mValues.put(mFirstPropertyName, valuesHolder);
+ 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);
@@ -323,15 +324,11 @@
public void setValues(PropertyValuesHolder... values) {
int numValues = values.length;
- mValues = new HashMap<String, PropertyValuesHolder>(numValues);
+ mValues = values;
+ mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
for (int i = 0; i < numValues; ++i) {
PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i];
- mValues.put(valuesHolder.getPropertyName(), valuesHolder);
- }
- if (numValues > 0 && values[0] != null) {
- mFirstPropertyName = ((PropertyValuesHolder) values[0]).getPropertyName();
- } else {
- mFirstPropertyName = "";
+ mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
}
}
@@ -348,26 +345,12 @@
* @param values The set of values to animate between.
*/
public void setValues(T... values) {
- if (values[0] instanceof PropertyValuesHolder) {
- int numValues = values.length;
- mValues = new HashMap<String, PropertyValuesHolder>(numValues);
- for (int i = 0; i < numValues; ++i) {
- PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i];
- mValues.put(valuesHolder.getPropertyName(), valuesHolder);
- }
- if (numValues > 0 && values[0] != null) {
- mFirstPropertyName = ((PropertyValuesHolder) values[0]).getPropertyName();
- } else {
- mFirstPropertyName = "";
- }
+ if (mValues == null || mValues.length == 0) {
+ setValues(new PropertyValuesHolder[]{
+ new PropertyValuesHolder("", (Object[])values)});
} else {
- if (mValues == null) {
- setValues(new PropertyValuesHolder[]{
- new PropertyValuesHolder("", (Object[])values)});
- } else {
- PropertyValuesHolder valuesHolder = mValues.get(mFirstPropertyName);
- valuesHolder.setValues(values);
- }
+ PropertyValuesHolder valuesHolder = mValues[0];
+ valuesHolder.setValues(values);
}
}
@@ -382,8 +365,9 @@
* that internal mechanisms for the animation are set up correctly.</p>
*/
void initAnimation() {
- for (PropertyValuesHolder pvHolder: mValues.values()) {
- pvHolder.init();
+ int numValues = mValues.length;
+ for (int i = 0; i < numValues; ++i) {
+ mValues[i].init();
}
mCurrentIteration = 0;
mInitialized = true;
@@ -394,8 +378,8 @@
* be between 0 and the total duration of the animation, including any repetition. If
* the animation has not yet been started, then it will not advance forward after it is
* set to this time; it will simply set the time to this value and perform any appropriate
- * actions based on that time. If the animation is already running, then seek() will
- * set the current playing time to this value and continue playing from that point.
+ * actions based on that time. If the animation is already running, then setCurrentPlayTime()
+ * will set the current playing time to this value and continue playing from that point.
*
* @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
*/
@@ -420,7 +404,7 @@
* @return The current position in time of the animation.
*/
public long getCurrentPlayTime() {
- if (!mInitialized) {
+ if (!mInitialized || mPlayingState == STOPPED) {
return 0;
}
return AnimationUtils.currentAnimationTimeMillis() - mStartTime;
@@ -587,7 +571,11 @@
* returns the animated value for the first of those objects.
*/
public Object getAnimatedValue() {
- return getAnimatedValue(mFirstPropertyName);
+ if (mValues != null && mValues.length > 0) {
+ return mValues[0].getAnimatedValue();
+ }
+ // Shouldn't get here; should always have values unless Animator was set up wrong
+ return null;
}
/**
@@ -601,7 +589,13 @@
* by this <code>Animator</code>.
*/
public Object getAnimatedValue(String propertyName) {
- return mValues.get(mFirstPropertyName).getAnimatedValue();
+ PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName);
+ if (valuesHolder != null) {
+ return valuesHolder.getAnimatedValue();
+ } else {
+ // At least avoid crashing if called with bogus propertyName
+ return null;
+ }
}
/**
@@ -691,6 +685,15 @@
}
/**
+ * Returns the timing interpolator that this Animator uses.
+ *
+ * @return The timing interpolator for this Animator.
+ */
+ public Interpolator getInterpolator() {
+ return mInterpolator;
+ }
+
+ /**
* The type evaluator to be used when calculating the animated values of this animation.
* The system will automatically assign a float, int, or double evaluator based on the type
* of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
@@ -707,8 +710,8 @@
* @param value the evaluator to be used this animation
*/
public void setEvaluator(TypeEvaluator value) {
- if (value != null && mValues != null) {
- mValues.get(mFirstPropertyName).setEvaluator(value);
+ if (value != null && mValues != null && mValues.length > 0) {
+ mValues[0].setEvaluator(value);
}
}
@@ -720,6 +723,10 @@
* @param playBackwards Whether the Animator should start playing in reverse.
*/
private void start(boolean 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;
sPendingAnimations.add(this);
@@ -731,6 +738,15 @@
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);
@@ -928,8 +944,9 @@
*/
void animateValue(float fraction) {
fraction = mInterpolator.getInterpolation(fraction);
- for (PropertyValuesHolder valuesHolder : mValues.values()) {
- valuesHolder.calculateValue(fraction);
+ int numValues = mValues.length;
+ for (int i = 0; i < numValues; ++i) {
+ mValues[i].calculateValue(fraction);
}
if (mUpdateListeners != null) {
int numListeners = mUpdateListeners.size();
@@ -939,6 +956,39 @@
}
}
+ @Override
+ public Animator clone() throws CloneNotSupportedException {
+ final Animator anim = (Animator) super.clone();
+ if (mUpdateListeners != null) {
+ ArrayList<AnimatorUpdateListener> oldListeners = mUpdateListeners;
+ anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
+ int numListeners = oldListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ anim.mUpdateListeners.add(oldListeners.get(i));
+ }
+ }
+ anim.mSeekTime = -1;
+ anim.mPlayingBackwards = false;
+ anim.mCurrentIteration = 0;
+ anim.mInitialized = false;
+ anim.mPlayingState = STOPPED;
+ anim.mStartedDelay = false;
+ PropertyValuesHolder[] oldValues = mValues;
+ if (oldValues != null) {
+ int numValues = oldValues.length;
+ anim.mValues = new PropertyValuesHolder[numValues];
+ for (int i = 0; i < numValues; ++i) {
+ anim.mValues[i] = oldValues[i];
+ }
+ anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
+ for (int i = 0; i < numValues; ++i) {
+ PropertyValuesHolder valuesHolder = mValues[i];
+ anim.mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
+ }
+ }
+ return anim;
+ }
+
/**
* Implementors of this interface can add themselves as update listeners
* to an <code>Animator</code> instance to receive callbacks on every animation
diff --git a/core/java/android/animation/PropertyAnimator.java b/core/java/android/animation/PropertyAnimator.java
index 9366a71..022ca7d 100644
--- a/core/java/android/animation/PropertyAnimator.java
+++ b/core/java/android/animation/PropertyAnimator.java
@@ -21,10 +21,7 @@
import android.util.AttributeSet;
import android.util.Log;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* This subclass of {@link Animator} provides support for animating properties on target objects.
@@ -61,10 +58,12 @@
*/
public void setPropertyName(String propertyName) {
if (mValues != null) {
- // should always be the case
- PropertyValuesHolder valuesHolder = mValues.get(mFirstPropertyName);
+ // mValues should always be non-null
+ PropertyValuesHolder valuesHolder = mValues[0];
+ String oldName = valuesHolder.getPropertyName();
valuesHolder.setPropertyName(propertyName);
- mFirstPropertyName = propertyName;
+ mValuesMap.remove(oldName);
+ mValuesMap.put(propertyName, valuesHolder);
}
mPropertyName = propertyName;
}
@@ -184,8 +183,9 @@
@Override
void initAnimation() {
super.initAnimation();
- for (PropertyValuesHolder valuesHolder : mValues.values()) {
- valuesHolder.setupSetterAndGetter(mTarget);
+ int numValues = mValues.length;
+ for (int i = 0; i < numValues; ++i) {
+ mValues[i].setupSetterAndGetter(mTarget);
}
}
@@ -223,8 +223,15 @@
@Override
void animateValue(float fraction) {
super.animateValue(fraction);
- for (PropertyValuesHolder valuesHolder : mValues.values()) {
- valuesHolder.setAnimatedValue(mTarget);
+ int numValues = mValues.length;
+ for (int i = 0; i < numValues; ++i) {
+ mValues[i].setAnimatedValue(mTarget);
}
}
+
+ @Override
+ public PropertyAnimator clone() throws CloneNotSupportedException {
+ final PropertyAnimator anim = (PropertyAnimator) super.clone();
+ return anim;
+ }
}
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 05e0bc1..fc829b8 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -261,11 +261,12 @@
// Swallow the error and keep trying other variants
}
}
+ // If we got here, then no appropriate function was found
+ Log.e("PropertyValuesHolder",
+ "Couldn't find setter/getter for property " + mPropertyName +
+ "with value type "+ mValueType);
}
- // If we got here, then no appropriate function was found
- Log.e("PropertyValuesHolder",
- "Couldn't find setter/getter for property " + mPropertyName +
- "with value type "+ mValueType);
+
return returnVal;
}
diff --git a/core/java/android/animation/Sequencer.java b/core/java/android/animation/Sequencer.java
index 2406d8a..7749429 100644
--- a/core/java/android/animation/Sequencer.java
+++ b/core/java/android/animation/Sequencer.java
@@ -46,10 +46,17 @@
public final class Sequencer extends Animatable {
/**
+ * 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
+ * to clone() to make deep copies of them.
+ */
+
+ /**
* Tracks animations currently being played, so that we know what to
* cancel or end when cancel() or end() is called on this Sequencer
*/
- private final ArrayList<Animatable> mPlayingSet = new ArrayList<Animatable>();
+ private ArrayList<Animatable> mPlayingSet = new ArrayList<Animatable>();
/**
* Contains all nodes, mapped to their respective Animatables. When new
@@ -57,21 +64,21 @@
* to a single node representing that Animatable, not create a new Node
* if one already exists.
*/
- private final HashMap<Animatable, Node> mNodeMap = new HashMap<Animatable, Node>();
+ private HashMap<Animatable, Node> mNodeMap = new HashMap<Animatable, Node>();
/**
* Set of all nodes created for this Sequencer. This list is used upon
* starting the sequencer, and the nodes are placed in sorted order into the
* sortedNodes collection.
*/
- private final ArrayList<Node> mNodes = new ArrayList<Node>();
+ private ArrayList<Node> mNodes = new ArrayList<Node>();
/**
* The sorted list of nodes. This is the order in which the animations will
* be played. The details about when exactly they will be played depend
* on the dependency relationships of the nodes.
*/
- private final ArrayList<Node> mSortedNodes = new ArrayList<Node>();
+ private ArrayList<Node> mSortedNodes = new ArrayList<Node>();
/**
* Flag indicating whether the nodes should be sorted prior to playing. This
@@ -283,6 +290,75 @@
}
}
+ @Override
+ public Sequencer clone() throws CloneNotSupportedException {
+ final Sequencer anim = (Sequencer) super.clone();
+ /*
+ * The basic clone() operation copies all items. This doesn't work very well for
+ * Sequencer, because it will copy references that need to be recreated and state
+ * that may not apply. What we need to do now is put the clone in an uninitialized
+ * state, with fresh, empty data structures. Then we will build up the nodes list
+ * manually, as we clone each Node (and its animation). The clone will then be sorted,
+ * and will populate any appropriate lists, when it is started.
+ */
+ anim.mNeedsSort = true;
+ anim.mCanceled = false;
+ anim.mPlayingSet = new ArrayList<Animatable>();
+ anim.mNodeMap = new HashMap<Animatable, Node>();
+ anim.mNodes = new ArrayList<Node>();
+ anim.mSortedNodes = new ArrayList<Node>();
+
+ // Walk through the old nodes list, cloning each node and adding it to the new nodemap.
+ // One problem is that the old node dependencies point to nodes in the old sequencer.
+ // We need to track the old/new nodes in order to reconstruct the dependencies in the clone.
+ HashMap<Node, Node> nodeCloneMap = new HashMap<Node, Node>(); // <old, new>
+ for (Node node : mNodes) {
+ Node nodeClone = node.clone();
+ nodeCloneMap.put(node, nodeClone);
+ anim.mNodes.add(nodeClone);
+ anim.mNodeMap.put(nodeClone.animation, nodeClone);
+ // Clear out the dependencies in the clone; we'll set these up manually later
+ nodeClone.dependencies = null;
+ nodeClone.tmpDependencies = null;
+ nodeClone.nodeDependents = null;
+ nodeClone.nodeDependencies = null;
+ // clear out any listeners that were set up by the sequencer; these will
+ // be set up when the clone's nodes are sorted
+ ArrayList<AnimatableListener> cloneListeners = nodeClone.animation.getListeners();
+ if (cloneListeners != null) {
+ ArrayList<AnimatableListener> listenersToRemove = null;
+ for (AnimatableListener listener : cloneListeners) {
+ if (listener instanceof SequencerAnimatableListener) {
+ if (listenersToRemove == null) {
+ listenersToRemove = new ArrayList<AnimatableListener>();
+ }
+ listenersToRemove.add(listener);
+ }
+ }
+ if (listenersToRemove != null) {
+ for (AnimatableListener listener : listenersToRemove) {
+ cloneListeners.remove(listener);
+ }
+ }
+ }
+ }
+ // Now that we've cloned all of the nodes, we're ready to walk through their
+ // dependencies, mapping the old dependencies to the new nodes
+ for (Node node : mNodes) {
+ Node nodeClone = nodeCloneMap.get(node);
+ if (node.dependencies != null) {
+ for (Dependency dependency : node.dependencies) {
+ Node clonedDependencyNode = nodeCloneMap.get(dependency.node);
+ Dependency cloneDependency = new Dependency(clonedDependencyNode,
+ dependency.rule);
+ nodeClone.addDependency(cloneDependency);
+ }
+ }
+ }
+
+ return anim;
+ }
+
/**
* This class is the mechanism by which animations are started based on events in other
* animations. If an animation has multiple dependencies on other animations, then
@@ -514,7 +590,7 @@
* both dependencies upon other nodes (in the dependencies list) as
* well as dependencies of other nodes upon this (in the nodeDependents list).
*/
- private static class Node {
+ private static class Node implements Cloneable {
public Animatable animation;
/**
@@ -587,6 +663,13 @@
}
dependencyNode.nodeDependents.add(this);
}
+
+ @Override
+ public Node clone() throws CloneNotSupportedException {
+ Node node = (Node) super.clone();
+ node.animation = (Animatable) animation.clone();
+ return node;
+ }
}
/**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d8e249e..4fb4bca 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3151,7 +3151,7 @@
(ApplicationInfo.FLAG_SYSTEM |
ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0 &&
!"user".equals(Build.TYPE)) {
- StrictMode.setThreadBlockingPolicy(
+ StrictMode.setThreadPolicy(
StrictMode.DISALLOW_DISK_WRITE |
StrictMode.DISALLOW_DISK_READ |
StrictMode.DISALLOW_NETWORK |
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 274a266..a0be0cd 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -330,7 +330,7 @@
}
/**
- * Similar to {@link Activity#onCreate}, you should initialized your dialog
+ * Similar to {@link Activity#onCreate}, you should initialize your dialog
* in this method, including calling {@link #setContentView}.
* @param savedInstanceState If this dialog is being reinitalized after a
* the hosting activity was previously shut down, holds the result from
diff --git a/core/java/android/bluetooth/AtCommandHandler.java b/core/java/android/bluetooth/AtCommandHandler.java
index 8de2133..6deab34 100644
--- a/core/java/android/bluetooth/AtCommandHandler.java
+++ b/core/java/android/bluetooth/AtCommandHandler.java
@@ -73,7 +73,7 @@
* least one element in this array.
* @return The result of this command.
*/
- // Typically used to set this paramter
+ // Typically used to set this parameter
public AtCommandResult handleSetCommand(Object[] args) {
return new AtCommandResult(AtCommandResult.ERROR);
}
@@ -83,11 +83,12 @@
* Test commands are part of the Extended command syntax, and are typically
* used to request an indication of the range of legal values that "FOO"
* can take.<p>
- * By defualt we return an OK result, to indicate that this command is at
+ * By default we return an OK result, to indicate that this command is at
* least recognized.<p>
* @return The result of this command.
*/
public AtCommandResult handleTestCommand() {
return new AtCommandResult(AtCommandResult.OK);
}
+
}
diff --git a/core/java/android/bluetooth/BluetoothAssignedNumbers.java b/core/java/android/bluetooth/BluetoothAssignedNumbers.java
new file mode 100644
index 0000000..55bc814
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAssignedNumbers.java
@@ -0,0 +1,523 @@
+/*
+ * 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.bluetooth;
+
+/**
+ * Bluetooth Assigned Numbers.
+ * <p>
+ * For now we only include Company ID values.
+ * @see <a href="https://www.bluetooth.org/technical/assignednumbers/identifiers.htm">
+ * The Official Bluetooth SIG Member Website | Company Identifiers</a>
+ *
+ * @hide
+ */
+public class BluetoothAssignedNumbers {
+
+ //// Bluetooth SIG Company ID values
+
+ /*
+ * Ericsson Technology Licensing.
+ */
+ public static final int ERICSSON_TECHNOLOGY = 0x0000;
+
+ /*
+ * Nokia Mobile Phones.
+ */
+ public static final int NOKIA_MOBILE_PHONES = 0x0001;
+
+ /*
+ * Intel Corp.
+ */
+ public static final int INTEL = 0x0002;
+
+ /*
+ * IBM Corp.
+ */
+ public static final int IBM = 0x0003;
+
+ /*
+ * Toshiba Corp.
+ */
+ public static final int TOSHIBA = 0x0004;
+
+ /*
+ * 3Com.
+ */
+ public static final int THREECOM = 0x0005;
+
+ /*
+ * Microsoft.
+ */
+ public static final int MICROSOFT = 0x0006;
+
+ /*
+ * Lucent.
+ */
+ public static final int LUCENT = 0x0007;
+
+ /*
+ * Motorola.
+ */
+ public static final int MOTOROLA = 0x0008;
+
+ /*
+ * Infineon Technologies AG.
+ */
+ public static final int INFINEON_TECHNOLOGIES = 0x0009;
+
+ /*
+ * Cambridge Silicon Radio.
+ */
+ public static final int CAMBRIDGE_SILICON_RADIO = 0x000A;
+
+ /*
+ * Silicon Wave.
+ */
+ public static final int SILICON_WAVE = 0x000B;
+
+ /*
+ * Digianswer A/S.
+ */
+ public static final int DIGIANSWER = 0x000C;
+
+ /*
+ * Texas Instruments Inc.
+ */
+ public static final int TEXAS_INSTRUMENTS = 0x000D;
+
+ /*
+ * Parthus Technologies Inc.
+ */
+ public static final int PARTHUS_TECHNOLOGIES = 0x000E;
+
+ /*
+ * Broadcom Corporation.
+ */
+ public static final int BROADCOM = 0x000F;
+
+ /*
+ * Mitel Semiconductor.
+ */
+ public static final int MITEL_SEMICONDUCTOR = 0x0010;
+
+ /*
+ * Widcomm, Inc.
+ */
+ public static final int WIDCOMM = 0x0011;
+
+ /*
+ * Zeevo, Inc.
+ */
+ public static final int ZEEVO = 0x0012;
+
+ /*
+ * Atmel Corporation.
+ */
+ public static final int ATMEL = 0x0013;
+
+ /*
+ * Mitsubishi Electric Corporation.
+ */
+ public static final int MITSUBISHI_ELECTRIC = 0x0014;
+
+ /*
+ * RTX Telecom A/S.
+ */
+ public static final int RTX_TELECOM = 0x0015;
+
+ /*
+ * KC Technology Inc.
+ */
+ public static final int KC_TECHNOLOGY = 0x0016;
+
+ /*
+ * Newlogic.
+ */
+ public static final int NEWLOGIC = 0x0017;
+
+ /*
+ * Transilica, Inc.
+ */
+ public static final int TRANSILICA = 0x0018;
+
+ /*
+ * Rohde & Schwarz GmbH & Co. KG.
+ */
+ public static final int ROHDE_AND_SCHWARZ = 0x0019;
+
+ /*
+ * TTPCom Limited.
+ */
+ public static final int TTPCOM = 0x001A;
+
+ /*
+ * Signia Technologies, Inc.
+ */
+ public static final int SIGNIA_TECHNOLOGIES = 0x001B;
+
+ /*
+ * Conexant Systems Inc.
+ */
+ public static final int CONEXANT_SYSTEMS = 0x001C;
+
+ /*
+ * Qualcomm.
+ */
+ public static final int QUALCOMM = 0x001D;
+
+ /*
+ * Inventel.
+ */
+ public static final int INVENTEL = 0x001E;
+
+ /*
+ * AVM Berlin.
+ */
+ public static final int AVM_BERLIN = 0x001F;
+
+ /*
+ * BandSpeed, Inc.
+ */
+ public static final int BANDSPEED = 0x0020;
+
+ /*
+ * Mansella Ltd.
+ */
+ public static final int MANSELLA = 0x0021;
+
+ /*
+ * NEC Corporation.
+ */
+ public static final int NEC = 0x0022;
+
+ /*
+ * WavePlus Technology Co., Ltd.
+ */
+ public static final int WAVEPLUS_TECHNOLOGY = 0x0023;
+
+ /*
+ * Alcatel.
+ */
+ public static final int ALCATEL = 0x0024;
+
+ /*
+ * Philips Semiconductors.
+ */
+ public static final int PHILIPS_SEMICONDUCTORS = 0x0025;
+
+ /*
+ * C Technologies.
+ */
+ public static final int C_TECHNOLOGIES = 0x0026;
+
+ /*
+ * Open Interface.
+ */
+ public static final int OPEN_INTERFACE = 0x0027;
+
+ /*
+ * R F Micro Devices.
+ */
+ public static final int RF_MICRO_DEVICES = 0x0028;
+
+ /*
+ * Hitachi Ltd.
+ */
+ public static final int HITACHI = 0x0029;
+
+ /*
+ * Symbol Technologies, Inc.
+ */
+ public static final int SYMBOL_TECHNOLOGIES = 0x002A;
+
+ /*
+ * Tenovis.
+ */
+ public static final int TENOVIS = 0x002B;
+
+ /*
+ * Macronix International Co. Ltd.
+ */
+ public static final int MACRONIX = 0x002C;
+
+ /*
+ * GCT Semiconductor.
+ */
+ public static final int GCT_SEMICONDUCTOR = 0x002D;
+
+ /*
+ * Norwood Systems.
+ */
+ public static final int NORWOOD_SYSTEMS = 0x002E;
+
+ /*
+ * MewTel Technology Inc.
+ */
+ public static final int MEWTEL_TECHNOLOGY = 0x002F;
+
+ /*
+ * ST Microelectronics.
+ */
+ public static final int ST_MICROELECTRONICS = 0x0030;
+
+ /*
+ * Synopsys.
+ */
+ public static final int SYNOPSYS = 0x0031;
+
+ /*
+ * Red-M (Communications) Ltd.
+ */
+ public static final int RED_M = 0x0032;
+
+ /*
+ * Commil Ltd.
+ */
+ public static final int COMMIL = 0x0033;
+
+ /*
+ * Computer Access Technology Corporation (CATC).
+ */
+ public static final int CATC = 0x0034;
+
+ /*
+ * Eclipse (HQ Espana) S.L.
+ */
+ public static final int ECLIPSE = 0x0035;
+
+ /*
+ * Renesas Technology Corp.
+ */
+ public static final int RENESAS_TECHNOLOGY = 0x0036;
+
+ /*
+ * Mobilian Corporation.
+ */
+ public static final int MOBILIAN_CORPORATION = 0x0037;
+
+ /*
+ * Terax.
+ */
+ public static final int TERAX = 0x0038;
+
+ /*
+ * Integrated System Solution Corp.
+ */
+ public static final int INTEGRATED_SYSTEM_SOLUTION = 0x0039;
+
+ /*
+ * Matsushita Electric Industrial Co., Ltd.
+ */
+ public static final int MATSUSHITA_ELECTRIC = 0x003A;
+
+ /*
+ * Gennum Corporation.
+ */
+ public static final int GENNUM = 0x003B;
+
+ /*
+ * Research In Motion.
+ */
+ public static final int RESEARCH_IN_MOTION = 0x003C;
+
+ /*
+ * IPextreme, Inc.
+ */
+ public static final int IPEXTREME = 0x003D;
+
+ /*
+ * Systems and Chips, Inc.
+ */
+ public static final int SYSTEMS_AND_CHIPS = 0x003E;
+
+ /*
+ * Bluetooth SIG, Inc.
+ */
+ public static final int BLUETOOTH_SIG = 0x003F;
+
+ /*
+ * Seiko Epson Corporation.
+ */
+ public static final int SEIKO_EPSON = 0x0040;
+
+ /*
+ * Integrated Silicon Solution Taiwan, Inc.
+ */
+ public static final int INTEGRATED_SILICON_SOLUTION = 0x0041;
+
+ /*
+ * CONWISE Technology Corporation Ltd.
+ */
+ public static final int CONWISE_TECHNOLOGY = 0x0042;
+
+ /*
+ * PARROT SA.
+ */
+ public static final int PARROT = 0x0043;
+
+ /*
+ * Socket Mobile.
+ */
+ public static final int SOCKET_MOBILE = 0x0044;
+
+ /*
+ * Atheros Communications, Inc.
+ */
+ public static final int ATHEROS_COMMUNICATIONS = 0x0045;
+
+ /*
+ * MediaTek, Inc.
+ */
+ public static final int MEDIATEK = 0x0046;
+
+ /*
+ * Bluegiga.
+ */
+ public static final int BLUEGIGA = 0x0047;
+
+ /*
+ * Marvell Technology Group Ltd.
+ */
+ public static final int MARVELL = 0x0048;
+
+ /*
+ * 3DSP Corporation.
+ */
+ public static final int THREE_DSP = 0x0049;
+
+ /*
+ * Accel Semiconductor Ltd.
+ */
+ public static final int ACCEL_SEMICONDUCTOR = 0x004A;
+
+ /*
+ * Continental Automotive Systems.
+ */
+ public static final int CONTINENTAL_AUTOMOTIVE = 0x004B;
+
+ /*
+ * Apple, Inc.
+ */
+ public static final int APPLE = 0x004C;
+
+ /*
+ * Staccato Communications, Inc.
+ */
+ public static final int STACCATO_COMMUNICATIONS = 0x004D;
+
+ /*
+ * Avago Technologies.
+ */
+ public static final int AVAGO = 0x004E;
+
+ /*
+ * APT Licensing Ltd.
+ */
+ public static final int APT_LICENSING = 0x004F;
+
+ /*
+ * SiRF Technology, Inc.
+ */
+ public static final int SIRF_TECHNOLOGY = 0x0050;
+
+ /*
+ * Tzero Technologies, Inc.
+ */
+ public static final int TZERO_TECHNOLOGIES = 0x0051;
+
+ /*
+ * J&M Corporation.
+ */
+ public static final int J_AND_M = 0x0052;
+
+ /*
+ * Free2move AB.
+ */
+ public static final int FREE2MOVE = 0x0053;
+
+ /*
+ * 3DiJoy Corporation.
+ */
+ public static final int THREE_DIJOY = 0x0054;
+
+ /*
+ * Plantronics, Inc.
+ */
+ public static final int PLANTRONICS = 0x0055;
+
+ /*
+ * Sony Ericsson Mobile Communications.
+ */
+ public static final int SONY_ERICSSON = 0x0056;
+
+ /*
+ * Harman International Industries, Inc.
+ */
+ public static final int HARMAN_INTERNATIONAL = 0x0057;
+
+ /*
+ * Vizio, Inc.
+ */
+ public static final int VIZIO = 0x0058;
+
+ /*
+ * Nordic Semiconductor ASA.
+ */
+ public static final int NORDIC_SEMICONDUCTOR = 0x0059;
+
+ /*
+ * EM Microelectronic-Marin SA.
+ */
+ public static final int EM_MICROELECTRONIC_MARIN = 0x005A;
+
+ /*
+ * Ralink Technology Corporation.
+ */
+ public static final int RALINK_TECHNOLOGY = 0x005B;
+
+ /*
+ * Belkin International, Inc.
+ */
+ public static final int BELKIN_INTERNATIONAL = 0x005C;
+
+ /*
+ * Realtek Semiconductor Corporation.
+ */
+ public static final int REALTEK_SEMICONDUCTOR = 0x005D;
+
+ /*
+ * Stonestreet One, LLC.
+ */
+ public static final int STONESTREET_ONE = 0x005E;
+
+ /*
+ * Wicentric, Inc.
+ */
+ public static final int WICENTRIC = 0x005F;
+
+ /*
+ * RivieraWaves S.A.S.
+ */
+ public static final int RIVIERAWAVES = 0x0060;
+
+ /*
+ * You can't instantiate one of these.
+ */
+ private BluetoothAssignedNumbers() {
+ }
+
+}
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
index 0c9bab2..c8381c9 100644
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ b/core/java/android/bluetooth/BluetoothClass.java
@@ -261,6 +261,10 @@
public static final int PROFILE_OPP = 2;
/** @hide */
public static final int PROFILE_HID = 3;
+ /** @hide */
+ public static final int PROFILE_PANU = 4;
+ /** @hide */
+ public static final int PROFILE_NAP = 5;
/**
* Check class bits for possible bluetooth profile support.
@@ -328,6 +332,12 @@
}
} else if (profile == PROFILE_HID) {
return (getDeviceClass() & Device.Major.PERIPHERAL) == Device.Major.PERIPHERAL;
+ } else if (profile == PROFILE_PANU || profile == PROFILE_NAP){
+ // No good way to distinguish between the two, based on class bits.
+ if (hasService(Service.NETWORKING)) {
+ return true;
+ }
+ return (getDeviceClass() & Device.Major.NETWORKING) == Device.Major.NETWORKING;
} else {
return false;
}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 4a91a8c..53d6a37 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -45,7 +45,7 @@
* This BluetoothHeadset object is not immediately bound to the
* BluetoothHeadset service. Use the ServiceListener interface to obtain a
* notification when it is bound, this is especially important if you wish to
- * immediately call methods on BluetootHeadset after construction.
+ * immediately call methods on BluetoothHeadset after construction.
*
* Android only supports one connected Bluetooth Headset at a time.
*
@@ -85,6 +85,43 @@
"android.bluetooth.headset.extra.DISCONNECT_INITIATOR";
/**
+ * Broadcast Action: Indicates a headset has posted a vendor-specific event.
+ * <p>Always contains the extra fields {@link #EXTRA_DEVICE},
+ * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD}, and
+ * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS}.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_VENDOR_SPECIFIC_HEADSET_EVENT =
+ "android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT";
+
+ /**
+ * A String extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
+ * intents that contains the name of the vendor-specific command.
+ */
+ public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD =
+ "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD";
+
+ /**
+ * An int extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
+ * intents that contains the Company ID of the vendor defining the vendor-specific
+ * command.
+ * @see <a href="https://www.bluetooth.org/Technical/AssignedNumbers/identifiers.htm">
+ * Bluetooth SIG Assigned Numbers - Company Identifiers</a>
+ */
+ public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID =
+ "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID";
+
+ /**
+ * A Parcelable String array extra field in
+ * {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} intents that contains
+ * the arguments to the vendor-specific command.
+ */
+ public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS =
+ "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_ARGS";
+
+
+ /**
* TODO(API release): Consider incorporating as new state in
* HEADSET_STATE_CHANGED
*/
@@ -108,7 +145,7 @@
public static final int RESULT_FAILURE = 0;
public static final int RESULT_SUCCESS = 1;
- /** Connection canceled before completetion. */
+ /** Connection canceled before completion. */
public static final int RESULT_CANCELED = 2;
/** Values for {@link #EXTRA_DISCONNECT_INITIATOR} */
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index fb3dfe4..3fbfc70 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -55,6 +55,8 @@
ParcelUuid.fromString("00001115-0000-1000-8000-00805F9B34FB");
public static final ParcelUuid NAP =
ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid BNEP =
+ ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB");
public static final ParcelUuid[] RESERVED_UUIDS = {
AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
@@ -92,13 +94,17 @@
return uuid.equals(Hid);
}
- public static boolean isPANU(ParcelUuid uuid) {
+ public static boolean isPanu(ParcelUuid uuid) {
return uuid.equals(PANU);
}
- public static boolean isNAP(ParcelUuid uuid) {
+ public static boolean isNap(ParcelUuid uuid) {
return uuid.equals(NAP);
}
+
+ public static boolean isBnep(ParcelUuid uuid) {
+ return uuid.equals(BNEP);
+ }
/**
* Returns true if ParcelUuid is present in uuidArray
*
diff --git a/core/java/android/bluetooth/HeadsetBase.java b/core/java/android/bluetooth/HeadsetBase.java
index e2935c9..9ef2eb5 100644
--- a/core/java/android/bluetooth/HeadsetBase.java
+++ b/core/java/android/bluetooth/HeadsetBase.java
@@ -74,8 +74,8 @@
private native void cleanupNativeDataNative();
- public HeadsetBase(PowerManager pm, BluetoothAdapter adapter, BluetoothDevice device,
- int rfcommChannel) {
+ public HeadsetBase(PowerManager pm, BluetoothAdapter adapter,
+ BluetoothDevice device, int rfcommChannel) {
mDirection = DIRECTION_OUTGOING;
mConnectTimestamp = System.currentTimeMillis();
mAdapter = adapter;
@@ -89,9 +89,10 @@
initializeNativeDataNative(-1);
}
- /* Create from an already exisiting rfcomm connection */
- public HeadsetBase(PowerManager pm, BluetoothAdapter adapter, BluetoothDevice device,
- int socketFd, int rfcommChannel, Handler handler) {
+ /* Create from an existing rfcomm connection */
+ public HeadsetBase(PowerManager pm, BluetoothAdapter adapter,
+ BluetoothDevice device,
+ int socketFd, int rfcommChannel, Handler handler) {
mDirection = DIRECTION_INCOMING;
mConnectTimestamp = System.currentTimeMillis();
mAdapter = adapter;
@@ -128,7 +129,7 @@
(System.currentTimeMillis() - timestamp) + " ms");
if (result.getResultCode() == AtCommandResult.ERROR) {
- Log.i(TAG, "Error pocessing <" + input + ">");
+ Log.i(TAG, "Error processing <" + input + ">");
}
sendURC(result.toString());
@@ -142,8 +143,9 @@
*/
protected void initializeAtParser() {
mAtParser = new AtParser();
- //TODO(): Get rid of this as there are no parsers registered. But because of dependencies,
- //it needs to be done as part of refactoring HeadsetBase and BluetoothHandsfree
+
+ //TODO(): Get rid of this as there are no parsers registered. But because of dependencies
+ // it needs to be done as part of refactoring HeadsetBase and BluetoothHandsfree
}
public AtParser getAtParser() {
@@ -159,8 +161,7 @@
String input = readNative(500);
if (input != null) {
handleInput(input);
- }
- else {
+ } else {
last_read_error = getLastReadStatusNative();
if (last_read_error != 0) {
Log.i(TAG, "headset read error " + last_read_error);
@@ -179,8 +180,6 @@
mEventThread.start();
}
-
-
private native String readNative(int timeout_ms);
private native int getLastReadStatusNative();
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 7901b155..244d126 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -389,15 +389,17 @@
if (permission != null) {
pw.println(prefix + "permission=" + permission);
}
- pw.println(prefix + "uid=" + uid + " taskAffinity=" + taskAffinity);
- if (theme != 0) {
- pw.println(prefix + "theme=0x" + Integer.toHexString(theme));
- }
- pw.println(prefix + "flags=0x" + Integer.toHexString(flags)
- + " processName=" + processName);
+ pw.println(prefix + "processName=" + processName);
+ pw.println(prefix + "taskAffinity=" + taskAffinity);
+ pw.println(prefix + "uid=" + uid + " flags=0x" + Integer.toHexString(flags)
+ + " theme=0x" + Integer.toHexString(theme));
pw.println(prefix + "sourceDir=" + sourceDir);
- pw.println(prefix + "publicSourceDir=" + publicSourceDir);
- pw.println(prefix + "resourceDirs=" + resourceDirs);
+ if (!sourceDir.equals(publicSourceDir)) {
+ pw.println(prefix + "publicSourceDir=" + publicSourceDir);
+ }
+ if (resourceDirs != null) {
+ pw.println(prefix + "resourceDirs=" + resourceDirs);
+ }
pw.println(prefix + "dataDir=" + dataDir);
if (sharedLibraryFiles != null) {
pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 155c86c..7c6e142 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1494,12 +1494,18 @@
ai.nonLocalizedLabel = v.coerceToString();
}
+ int defaultTheme = 0;
+ if (owner.applicationInfo.targetSdkVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {
+ // As of honeycomb, the default application theme is holographic.
+ defaultTheme = android.R.style.Theme_Holo;
+ }
+
ai.icon = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
ai.logo = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
ai.theme = sa.getResourceId(
- com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
+ com.android.internal.R.styleable.AndroidManifestApplication_theme, defaultTheme);
ai.descriptionRes = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 03aa968..38d6526 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -651,14 +651,40 @@
* @return the number of rows in the table
*/
public static long queryNumEntries(SQLiteDatabase db, String table) {
- Cursor cursor = db.query(table, countProjection,
- null, null, null, null, null);
- try {
- cursor.moveToFirst();
- return cursor.getLong(0);
- } finally {
- cursor.close();
- }
+ return queryNumEntries(db, table, null, null);
+ }
+
+ /**
+ * Query the table for the number of rows in the table.
+ * @param db the database the table is in
+ * @param table the name of the table to query
+ * @param selection A filter declaring which rows to return,
+ * formatted as an SQL WHERE clause (excluding the WHERE itself).
+ * Passing null will count all rows for the given table
+ * @return the number of rows in the table filtered by the selection
+ */
+ public static long queryNumEntries(SQLiteDatabase db, String table, String selection) {
+ return queryNumEntries(db, table, selection, null);
+ }
+
+ /**
+ * Query the table for the number of rows in the table.
+ * @param db the database the table is in
+ * @param table the name of the table to query
+ * @param selection A filter declaring which rows to return,
+ * formatted as an SQL WHERE clause (excluding the WHERE itself).
+ * Passing null will count all rows for the given table
+ * @param selectionArgs You may include ?s in selection,
+ * which will be replaced by the values from selectionArgs,
+ * in order that they appear in the selection.
+ * The values will be bound as Strings.
+ * @return the number of rows in the table filtered by the selection
+ */
+ public static long queryNumEntries(SQLiteDatabase db, String table, String selection,
+ String[] selectionArgs) {
+ String s = (!TextUtils.isEmpty(selection)) ? " where " + selection : "";
+ return longForQuery(db, "select count(*) from " + table + s,
+ selectionArgs);
}
/**
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index dc3b469..b83d5ad 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -2066,11 +2066,9 @@
* mapping is NOT replaced with the new mapping).
*/
/* package */ void addToCompiledQueries(String sql, SQLiteCompiledSql compiledStatement) {
- SQLiteCompiledSql compiledSql = null;
synchronized(mCompiledQueries) {
// don't insert the new mapping if a mapping already exists
- compiledSql = mCompiledQueries.get(sql);
- if (compiledSql != null) {
+ if (mCompiledQueries.containsKey(sql)) {
return;
}
@@ -2392,10 +2390,9 @@
ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
// make a local copy of mActiveDatabases - so that this method is not competing
// for synchronization lock on mActiveDatabases
- ArrayList<WeakReference<SQLiteDatabase>> tempList =
- new ArrayList<WeakReference<SQLiteDatabase>>();
+ ArrayList<WeakReference<SQLiteDatabase>> tempList;
synchronized(mActiveDatabases) {
- Collections.copy(tempList, mActiveDatabases);
+ tempList = (ArrayList<WeakReference<SQLiteDatabase>>)mActiveDatabases.clone();
}
for (WeakReference<SQLiteDatabase> w : tempList) {
SQLiteDatabase db = w.get();
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index d8cce21..ccf8d68 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -121,8 +121,13 @@
* @return a read/write database object valid until {@link #close} is called
*/
public synchronized SQLiteDatabase getWritableDatabase() {
- if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
- return mDatabase; // The database is already open for business
+ if (mDatabase != null) {
+ if (!mDatabase.isOpen()) {
+ // darn! the user closed the database by calling mDatabase.close()
+ mDatabase = null;
+ } else if (!mDatabase.isReadOnly()) {
+ return mDatabase; // The database is already open for business
+ }
}
if (mIsInitializing) {
@@ -207,8 +212,13 @@
* or {@link #close} is called.
*/
public synchronized SQLiteDatabase getReadableDatabase() {
- if (mDatabase != null && mDatabase.isOpen()) {
- return mDatabase; // The database is already open for business
+ if (mDatabase != null) {
+ if (!mDatabase.isOpen()) {
+ // darn! the user closed the database by calling mDatabase.close()
+ mDatabase = null;
+ } else {
+ return mDatabase; // The database is already open for business
+ }
}
if (mIsInitializing) {
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 231d8e6..9b7d823 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -158,18 +158,18 @@
@Override
protected void onAllReferencesReleased() {
- releaseCompiledSqlIfNotInCache();
+ release();
mDatabase.removeSQLiteClosable(this);
mDatabase.releaseReference();
}
@Override
protected void onAllReferencesReleasedFromContainer() {
- releaseCompiledSqlIfNotInCache();
+ release();
mDatabase.releaseReference();
}
- /* package */ synchronized void releaseCompiledSqlIfNotInCache() {
+ /* package */ synchronized void release() {
if (mCompiledSql == null) {
return;
}
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index 14de60f..dc07db0 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -265,7 +265,7 @@
clearBindings();
// release the compiled sql statement so that the caller's SQLiteStatement no longer
// has a hard reference to a database object that may get deallocated at any point.
- releaseCompiledSqlIfNotInCache();
+ release();
// restore the database connection handle to the original value
mDatabase = mOrigDb;
nHandle = mDatabase.mNativeHandle;
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index a0abc6c..e432a47 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -960,6 +960,7 @@
private static final String KEY_PREVIEW_SIZE = "preview-size";
private static final String KEY_PREVIEW_FORMAT = "preview-format";
private static final String KEY_PREVIEW_FRAME_RATE = "preview-frame-rate";
+ private static final String KEY_PREVIEW_FPS_RANGE = "preview-fps-range";
private static final String KEY_PICTURE_SIZE = "picture-size";
private static final String KEY_PICTURE_FORMAT = "picture-format";
private static final String KEY_JPEG_THUMBNAIL_SIZE = "jpeg-thumbnail-size";
@@ -1219,6 +1220,22 @@
*/
public static final String METERING_MODE_SPOT = "spot";
+ /**
+ * The array index of minimum preview fps for use with {@link
+ * #getPreviewFpsRange(int[])} or {@link
+ * #getSupportedPreviewFpsRange()}.
+ * @hide
+ */
+ public static final int PREVIEW_FPS_MIN_INDEX = 0;
+
+ /**
+ * The array index of maximum preview fps for use with {@link
+ * #getPreviewFpsRange(int[])} or {@link
+ * #getSupportedPreviewFpsRange()}.
+ * @hide
+ */
+ public static final int PREVIEW_FPS_MAX_INDEX = 1;
+
// Formats for setPreviewFormat and setPictureFormat.
private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp";
private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp";
@@ -1482,6 +1499,64 @@
}
/**
+ * Sets the maximum and maximum preview fps. This controls the rate of
+ * preview frames received in {@link #PreviewCallback}. The minimum and
+ * maximum preview fps must be one of the elements from {@link
+ * #getSupportedPreviewFpsRange}.
+ *
+ * @param min the minimum preview fps (scaled by 1000).
+ * @param max the maximum preview fps (scaled by 1000).
+ * @throws RuntimeException if fps range is invalid.
+ * @see #setPreviewCallbackWithBuffer(Camera.PreviewCallback)
+ * @see #getSupportedPreviewFpsRange()
+ * @hide
+ */
+ public void setPreviewFpsRange(int min, int max) {
+ set(KEY_PREVIEW_FPS_RANGE, "" + min + "," + max);
+ }
+
+ /**
+ * Returns the current minimum and maximum preview fps. The values are
+ * one of the elements returned by {@link #getSupportedPreviewFpsRange}.
+ *
+ * @return range the minimum and maximum preview fps (scaled by 1000).
+ * @see #PREVIEW_FPS_MIN_INDEX
+ * @see #PREVIEW_FPS_MAX_INDEX
+ * @see #getSupportedPreviewFpsRange()
+ * @hide
+ */
+ public void getPreviewFpsRange(int[] range) {
+ if (range == null || range.length != 2) {
+ throw new IllegalArgumentException(
+ "range must be an float array with two elements.");
+ }
+ splitInt(get(KEY_PREVIEW_FPS_RANGE), range);
+ }
+
+ /**
+ * Gets the supported preview fps (frame-per-second) ranges. Each range
+ * contains a minimum fps and maximum fps. If minimum fps equals to
+ * maximum fps, the camera outputs frames in fixed frame rate. If not,
+ * the camera outputs frames in auto frame rate. The actual frame rate
+ * fluctuates between the minimum and the maximum. The values are
+ * multiplied by 1000 and represented in integers. For example, if frame
+ * rate is 26.623 frames per second, the value is 26623.
+ *
+ * @return a list of supported preview fps ranges. This method returns a
+ * list with at least one element. Every element is an int array
+ * of two values - minimum fps and maximum fps. The list is
+ * sorted from small to large (first by maximum fps and then
+ * minimum fps).
+ * @see #PREVIEW_FPS_MIN_INDEX
+ * @see #PREVIEW_FPS_MAX_INDEX
+ * @hide
+ */
+ public List<int[]> getSupportedPreviewFpsRange() {
+ String str = get(KEY_PREVIEW_FPS_RANGE + SUPPORTED_VALUES_SUFFIX);
+ return splitRange(str);
+ }
+
+ /**
* Sets the image format for preview pictures.
* <p>If this is never called, the default format will be
* {@link android.graphics.ImageFormat#NV21}, which
@@ -2184,10 +2259,7 @@
throw new IllegalArgumentException(
"output must be an float array with three elements.");
}
- List<Float> distances = splitFloat(get(KEY_FOCUS_DISTANCES));
- output[0] = distances.get(0);
- output[1] = distances.get(1);
- output[2] = distances.get(2);
+ splitFloat(get(KEY_FOCUS_DISTANCES), output);
}
/**
@@ -2255,19 +2327,27 @@
return substrings;
}
- // Splits a comma delimited string to an ArrayList of Float.
- // Return null if the passing string is null or the size is 0.
- private ArrayList<Float> splitFloat(String str) {
- if (str == null) return null;
+ private void splitInt(String str, int[] output) {
+ if (str == null) return;
StringTokenizer tokenizer = new StringTokenizer(str, ",");
- ArrayList<Float> substrings = new ArrayList<Float>();
+ int index = 0;
while (tokenizer.hasMoreElements()) {
String token = tokenizer.nextToken();
- substrings.add(Float.parseFloat(token));
+ output[index++] = Integer.parseInt(token);
}
- if (substrings.size() == 0) return null;
- return substrings;
+ }
+
+ // Splits a comma delimited string to an ArrayList of Float.
+ private void splitFloat(String str, float[] output) {
+ if (str == null) return;
+
+ StringTokenizer tokenizer = new StringTokenizer(str, ",");
+ int index = 0;
+ while (tokenizer.hasMoreElements()) {
+ String token = tokenizer.nextToken();
+ output[index++] = Float.parseFloat(token);
+ }
}
// Returns the value of a float parameter.
@@ -2318,5 +2398,30 @@
Log.e(TAG, "Invalid size parameter string=" + str);
return null;
}
+
+ // Splits a comma delimited string to an ArrayList of int array.
+ // Example string: "(10000,26623),(10000,30000)". Return null if the
+ // passing string is null or the size is 0.
+ private ArrayList<int[]> splitRange(String str) {
+ if (str == null || str.charAt(0) != '('
+ || str.charAt(str.length() - 1) != ')') {
+ Log.e(TAG, "Invalid range list string=" + str);
+ return null;
+ }
+
+ ArrayList<int[]> rangeList = new ArrayList<int[]>();
+ int endIndex, fromIndex = 1;
+ do {
+ int[] range = new int[2];
+ endIndex = str.indexOf("),(", fromIndex);
+ if (endIndex == -1) endIndex = str.length() - 1;
+ splitInt(str.substring(fromIndex, endIndex), range);
+ rangeList.add(range);
+ fromIndex = endIndex + 3;
+ } while (endIndex != str.length() - 1);
+
+ if (rangeList.size() == 0) return null;
+ return rangeList;
+ }
};
}
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index b49a409..f2b907b 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -77,6 +77,27 @@
public static final int TYPE_PROXIMITY = 8;
/**
+ * A constant describing a gravity sensor type.
+ * See {@link android.hardware.SensorEvent SensorEvent}
+ * for more details.
+ */
+ public static final int TYPE_GRAVITY = 9;
+
+ /**
+ * A constant describing a linear acceleration sensor type.
+ * See {@link android.hardware.SensorEvent SensorEvent}
+ * for more details.
+ */
+ public static final int TYPE_LINEAR_ACCELERATION = 10;
+
+ /**
+ * A constant describing a rotation vector sensor type.
+ * See {@link android.hardware.SensorEvent SensorEvent}
+ * for more details.
+ */
+ public static final int TYPE_ROTATION_VECTOR = 11;
+
+ /**
* A constant describing all sensor types.
*/
public static final int TYPE_ALL = -1;
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index aaf3898..2c5c909 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -133,6 +133,16 @@
* All values are in micro-Tesla (uT) and measure the ambient magnetic field
* in the X, Y and Z axis.
*
+ * <h4>{@link android.hardware.Sensor#TYPE_GYROSCOPE Sensor.TYPE_GYROSCOPE}:</h4>
+ * All values are in radians/second and measure the rate of rotation
+ * around the X, Y and Z axis. The coordinate system is the same as is
+ * used for the acceleration sensor. Rotation is positive in the counter-clockwise
+ * direction. That is, an observer looking from some positive location on the x, y.
+ * or z axis at a device positioned on the origin would report positive rotation
+ * if the device appeared to be rotating counter clockwise. Note that this is the
+ * standard mathematical definition of positive rotation and does not agree with the
+ * definition of roll given earlier.
+ *
* <h4>{@link android.hardware.Sensor#TYPE_LIGHT Sensor.TYPE_LIGHT}:</h4>
*
* <ul>
@@ -155,6 +165,27 @@
* the <i>far</i> state and a lesser value in the <i>near</i> state.
* </p>
*
+ * <h4>{@link android.hardware.Sensor#TYPE_GRAVITY Sensor.TYPE_GRAVITY}:</h4>
+ * A three dimensional vector indicating the direction and magnitude of gravity. Units
+ * are m/s^2. The coordinate system is the same as is used by the acceleration sensor.
+ *
+ * <h4>{@link android.hardware.Sensor#TYPE_LINEAR_ACCELERATION Sensor.TYPE_LINEAR_ACCELERATION}:</h4>
+ * A three dimensional vector indicating acceleration along each device axis, not including
+ * gravity. All values have units of m/s^2. The coordinate system is the same as is used by the
+ * acceleration sensor.
+ *
+ * <h4>{@link android.hardware.Sensor#TYPE_ROTATION_VECTOR Sensor.TYPE_ROTATION_VECTOR}:</h4>
+ * The rotation vector represents the orientation of the device as a combination of an angle
+ * and an axis, in which the device has rotated through an angle theta around an axis
+ * <x, y, z>. The three elements of the rotation vector are
+ * <x*sin(theta/2), y*sin(theta/2), z*sin(theta/2)>, such that the magnitude of the rotation
+ * vector is equal to sin(theta/2), and the direction of the rotation vector is equal to the
+ * direction of the axis of rotation. The three elements of the rotation vector are equal to
+ * the last three components of a unit quaternion
+ * <cos(theta/2), x*sin(theta/2), y*sin(theta/2), z*sin(theta/2)>. Elements of the rotation
+ * vector are unitless. The x,y, and z axis are defined in the same way as the acceleration
+ * sensor.
+ *
* <h4>{@link android.hardware.Sensor#TYPE_ORIENTATION
* Sensor.TYPE_ORIENTATION}:</h4> All values are angles in degrees.
*
@@ -201,6 +232,7 @@
* @see SensorEvent
* @see GeomagneticField
*/
+
public final float[] values;
/**
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index d2c3eaa..97921fe 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1769,6 +1769,183 @@
}
+ /** Helper function to compute the angle change between two rotation matrices.
+ * Given a current rotation matrix (R) and a previous rotation matrix
+ * (prevR) computes the rotation around the x,y, and z axes which
+ * transforms prevR to R.
+ * outputs a 3 element vector containing the x,y, and z angle
+ * change at indexes 0, 1, and 2 respectively.
+ * <p> Each input matrix is either as a 3x3 or 4x4 row-major matrix
+ * depending on the length of the passed array:
+ * <p>If the array length is 9, then the array elements represent this matrix
+ * <pre>
+ * / R[ 0] R[ 1] R[ 2] \
+ * | R[ 3] R[ 4] R[ 5] |
+ * \ R[ 6] R[ 7] R[ 8] /
+ *</pre>
+ * <p>If the array length is 16, then the array elements represent this matrix
+ * <pre>
+ * / R[ 0] R[ 1] R[ 2] R[ 3] \
+ * | R[ 4] R[ 5] R[ 6] R[ 7] |
+ * | R[ 8] R[ 9] R[10] R[11] |
+ * \ R[12] R[13] R[14] R[15] /
+ *</pre>
+ * @param R current rotation matrix
+ * @param prevR previous rotation matrix
+ * @param angleChange an array of floats in which the angle change is stored
+ */
+
+ public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) {
+ float rd1=0,rd4=0, rd6=0,rd7=0, rd8=0;
+ float ri0=0,ri1=0,ri2=0,ri3=0,ri4=0,ri5=0,ri6=0,ri7=0,ri8=0;
+ float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0;
+ int i, j, k;
+
+ if(R.length == 9) {
+ ri0 = R[0];
+ ri1 = R[1];
+ ri2 = R[2];
+ ri3 = R[3];
+ ri4 = R[4];
+ ri5 = R[5];
+ ri6 = R[6];
+ ri7 = R[7];
+ ri8 = R[8];
+ } else if(R.length == 16) {
+ ri0 = R[0];
+ ri1 = R[1];
+ ri2 = R[2];
+ ri3 = R[4];
+ ri4 = R[5];
+ ri5 = R[6];
+ ri6 = R[8];
+ ri7 = R[9];
+ ri8 = R[10];
+ }
+
+ if(prevR.length == 9) {
+ pri0 = R[0];
+ pri1 = R[1];
+ pri2 = R[2];
+ pri3 = R[3];
+ pri4 = R[4];
+ pri5 = R[5];
+ pri6 = R[6];
+ pri7 = R[7];
+ pri8 = R[8];
+ } else if(prevR.length == 16) {
+ pri0 = R[0];
+ pri1 = R[1];
+ pri2 = R[2];
+ pri3 = R[4];
+ pri4 = R[5];
+ pri5 = R[6];
+ pri6 = R[8];
+ pri7 = R[9];
+ pri8 = R[10];
+ }
+
+ // calculate the parts of the rotation difference matrix we need
+ // rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j];
+
+ rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1]
+ rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1]
+ rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0]
+ rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1]
+ rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2]
+
+ angleChange[0] = (float)Math.atan2(rd1, rd4);
+ angleChange[1] = (float)Math.asin(-rd7);
+ angleChange[2] = (float)Math.atan2(-rd6, rd8);
+
+ }
+
+ /** Helper function to convert a rotation vector to a rotation matrix.
+ * Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a
+ * 9 or 16 element rotation matrix in the array R. R must have length 9 or 16.
+ * If R.length == 9, the following matrix is returned:
+ * <pre>
+ * / R[ 0] R[ 1] R[ 2] \
+ * | R[ 3] R[ 4] R[ 5] |
+ * \ R[ 6] R[ 7] R[ 8] /
+ *</pre>
+ * If R.length == 16, the following matrix is returned:
+ * <pre>
+ * / R[ 0] R[ 1] R[ 2] 0 \
+ * | R[ 4] R[ 5] R[ 6] 0 |
+ * | R[ 8] R[ 9] R[10] 0 |
+ * \ 0 0 0 1 /
+ *</pre>
+ * @param rotationVector the rotation vector to convert
+ * @param R an array of floats in which to store the rotation matrix
+ */
+ public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {
+ float q0 = (float)Math.sqrt(1 - rotationVector[0]*rotationVector[0] -
+ rotationVector[1]*rotationVector[1] -
+ rotationVector[2]*rotationVector[2]);
+ float q1 = rotationVector[0];
+ float q2 = rotationVector[1];
+ float q3 = rotationVector[2];
+
+ float sq_q1 = 2 * q1 * q1;
+ float sq_q2 = 2 * q2 * q2;
+ float sq_q3 = 2 * q3 * q3;
+ float q1_q2 = 2 * q1 * q2;
+ float q3_q0 = 2 * q3 * q0;
+ float q1_q3 = 2 * q1 * q3;
+ float q2_q0 = 2 * q2 * q0;
+ float q2_q3 = 2 * q2 * q3;
+ float q1_q0 = 2 * q1 * q0;
+
+ if(R.length == 9) {
+ R[0] = 1 - sq_q2 - sq_q3;
+ R[1] = q1_q2 - q3_q0;
+ R[2] = q1_q3 + q2_q0;
+
+ R[3] = q1_q2 + q3_q0;
+ R[4] = 1 - sq_q1 - sq_q3;
+ R[5] = q2_q3 - q1_q0;
+
+ R[6] = q1_q3 - q2_q0;
+ R[7] = q2_q3 + q1_q0;
+ R[8] = 1 - sq_q1 - sq_q2;
+ } else if (R.length == 16) {
+ R[0] = 1 - sq_q2 - sq_q3;
+ R[1] = q1_q2 - q3_q0;
+ R[2] = q1_q3 + q2_q0;
+ R[3] = 0.0f;
+
+ R[4] = q1_q2 + q3_q0;
+ R[5] = 1 - sq_q1 - sq_q3;
+ R[6] = q2_q3 - q1_q0;
+ R[7] = 0.0f;
+
+ R[8] = q1_q3 - q2_q0;
+ R[9] = q2_q3 + q1_q0;
+ R[10] = 1 - sq_q1 - sq_q2;
+ R[11] = 0.0f;
+
+ R[12] = R[13] = R[14] = 0.0f;
+ R[15] = 1.0f;
+ }
+ }
+
+ /** Helper function to convert a rotation vector to a normalized quaternion.
+ * Given a rotation vector (presumably from a ROTATION_VECTOR sensor), returns a normalized
+ * quaternion in the array Q. The quaternion is stored as [w, x, y, z]
+ * @param rv the rotation vector to convert
+ * @param Q an array of floats in which to store the computed quaternion
+ */
+ public static void getQuaternionFromVector(float[] Q, float[] rv) {
+ float w = (float)Math.sqrt(1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2]);
+ //In this case, the w component of the quaternion is known to be a positive number
+
+ Q[0] = w;
+ Q[1] = rv[0];
+ Q[2] = rv[1];
+ Q[3] = rv[2];
+ }
+
private static native void nativeClassInit();
private static native int sensors_module_init();
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 95f217f..9fe6e01 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1400,6 +1400,7 @@
pw.println(getDischargeStartLevel());
pw.print(prefix); pw.print(" Discharge cycle current level: ");
pw.println(getDischargeCurrentLevel());
+ } else {
pw.print(prefix); pw.println(" Device is currently plugged into power");
pw.print(prefix); pw.print(" Last discharge cycle start level: ");
pw.println(getDischargeStartLevel());
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 8624467..9268cd1 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -206,7 +206,8 @@
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
* <ul>
- * <li> Alerts UI change?
+ * <li> The default theme for applications is now dark holographic:
+ * {@link android.R.style#Theme_Holo}.
* </ul>
*/
public static final int HONEYCOMB = CUR_DEVELOPMENT;
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 49b72fe..eb941e4 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -73,7 +73,18 @@
* receiver.
*/
public Messenger replyTo;
-
+
+ /** If set message is in use */
+ /*package*/ static final int FLAG_IN_USE = 1;
+
+ /** Flags reserved for future use (All are reserved for now) */
+ /*package*/ static final int FLAGS_RESERVED = ~FLAG_IN_USE;
+
+ /** Flags to clear in the copyFrom method */
+ /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAGS_RESERVED | FLAG_IN_USE;
+
+ /*package*/ int flags;
+
/*package*/ long when;
/*package*/ Bundle data;
@@ -253,6 +264,7 @@
* target/callback of the original message.
*/
public void copyFrom(Message o) {
+ this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM;
this.what = o.what;
this.arg1 = o.arg1;
this.arg2 = o.arg2;
@@ -350,6 +362,7 @@
}
/*package*/ void clearForRecycle() {
+ flags = 0;
what = 0;
arg1 = 0;
arg2 = 0;
@@ -361,6 +374,14 @@
data = null;
}
+ /*package*/ boolean isInUse() {
+ return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
+ }
+
+ /*package*/ void markInUse() {
+ flags |= FLAG_IN_USE;
+ }
+
/** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
*/
public Message() {
@@ -453,4 +474,3 @@
replyTo = Messenger.readMessengerOrNullFromParcel(source);
}
}
-
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index adb11c8..75dfdd2 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -120,6 +120,7 @@
now = SystemClock.uptimeMillis();
Message msg = pullNextLocked(now);
if (msg != null) {
+ msg.markInUse();
return msg;
}
@@ -192,7 +193,7 @@
}
final boolean enqueueMessage(Message msg, long when) {
- if (msg.when != 0) {
+ if (msg.isInUse()) {
throw new AndroidRuntimeException(msg
+ " This message is already in use.");
}
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index ac12e10..7f7b02b 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -114,7 +114,7 @@
*
* @param policyMask a bitmask of DISALLOW_* and PENALTY_* values.
*/
- public static void setThreadBlockingPolicy(final int policyMask) {
+ public static void setThreadPolicy(final int policyMask) {
// In addition to the Java-level thread-local in Dalvik's
// BlockGuard, we also need to keep a native thread-local in
// Binder in order to propagate the value across Binder calls,
@@ -164,11 +164,43 @@
*
* @return the bitmask of all the DISALLOW_* and PENALTY_* bits currently enabled
*/
- public static int getThreadBlockingPolicy() {
+ public static int getThreadPolicy() {
return BlockGuard.getThreadPolicy().getPolicyMask();
}
/**
+ * Updates the current thread's policy mask to allow reading &
+ * writing to disk.
+ *
+ * @return the old policy mask, to be passed to setThreadPolicy to
+ * restore the policy.
+ */
+ public static int allowThreadDiskWrites() {
+ int oldPolicy = getThreadPolicy();
+ int newPolicy = oldPolicy & ~(DISALLOW_DISK_WRITE | DISALLOW_DISK_READ);
+ if (newPolicy != oldPolicy) {
+ setThreadPolicy(newPolicy);
+ }
+ return oldPolicy;
+ }
+
+ /**
+ * Updates the current thread's policy mask to allow reading from
+ * disk.
+ *
+ * @return the old policy mask, to be passed to setThreadPolicy to
+ * restore the policy.
+ */
+ public static int allowThreadDiskReads() {
+ int oldPolicy = getThreadPolicy();
+ int newPolicy = oldPolicy & ~(DISALLOW_DISK_READ);
+ if (newPolicy != oldPolicy) {
+ setThreadPolicy(newPolicy);
+ }
+ return oldPolicy;
+ }
+
+ /**
* Parses the BlockGuard policy mask out from the Exception's
* getMessage() String value. Kinda gross, but least
* invasive. :/
@@ -413,13 +445,13 @@
if (violationMaskSubset != 0) {
int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
violationMaskSubset |= violationBit;
- final int savedPolicy = getThreadBlockingPolicy();
+ final int savedPolicy = getThreadPolicy();
try {
// First, remove any policy before we call into the Activity Manager,
// otherwise we'll infinite recurse as we try to log policy violations
// to disk, thus violating policy, thus requiring logging, etc...
// We restore the current policy below, in the finally block.
- setThreadBlockingPolicy(0);
+ setThreadPolicy(0);
ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
RuntimeInit.getApplicationObject(),
@@ -429,7 +461,7 @@
Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
} finally {
// Restore the policy.
- setThreadBlockingPolicy(savedPolicy);
+ setThreadPolicy(savedPolicy);
}
}
@@ -487,7 +519,7 @@
new LogStackTrace().printStackTrace(new PrintWriter(sw));
String ourStack = sw.toString();
- int policyMask = getThreadBlockingPolicy();
+ int policyMask = getThreadPolicy();
boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
int numViolations = p.readInt();
diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl
deleted file mode 100644
index 5c69214..0000000
--- a/core/java/android/os/storage/IMountService.aidl
+++ /dev/null
@@ -1,184 +0,0 @@
-/* //device/java/android/android/os/IUsb.aidl
-**
-** 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.
-*/
-
-package android.os.storage;
-
-import android.os.storage.IMountServiceListener;
-import android.os.storage.IMountShutdownObserver;
-import android.os.storage.IObbActionListener;
-
-/** WARNING! Update IMountService.h and IMountService.cpp if you change this file.
- * In particular, the ordering of the methods below must match the
- * _TRANSACTION enum in IMountService.cpp
- * @hide - Applications should use android.os.storage.StorageManager to access
- * storage functions.
- */
-interface IMountService
-{
- /**
- * Registers an IMountServiceListener for receiving async
- * notifications.
- */
- void registerListener(IMountServiceListener listener);
-
- /**
- * Unregisters an IMountServiceListener
- */
- void unregisterListener(IMountServiceListener listener);
-
- /**
- * Returns true if a USB mass storage host is connected
- */
- boolean isUsbMassStorageConnected();
-
- /**
- * Enables / disables USB mass storage.
- * The caller should check actual status of enabling/disabling
- * USB mass storage via StorageEventListener.
- */
- void setUsbMassStorageEnabled(boolean enable);
-
- /**
- * Returns true if a USB mass storage host is enabled (media is shared)
- */
- boolean isUsbMassStorageEnabled();
-
- /**
- * Mount external storage at given mount point.
- * Returns an int consistent with MountServiceResultCode
- */
- int mountVolume(String mountPoint);
-
- /**
- * Safely unmount external storage at given mount point.
- * The unmount is an asynchronous operation. Applications
- * should register StorageEventListener for storage related
- * status changes.
- *
- */
- void unmountVolume(String mountPoint, boolean force);
-
- /**
- * Format external storage given a mount point.
- * Returns an int consistent with MountServiceResultCode
- */
- int formatVolume(String mountPoint);
-
- /**
- * Returns an array of pids with open files on
- * the specified path.
- */
- int[] getStorageUsers(String path);
-
- /**
- * Gets the state of a volume via its mountpoint.
- */
- String getVolumeState(String mountPoint);
-
- /*
- * Creates a secure container with the specified parameters.
- * Returns an int consistent with MountServiceResultCode
- */
- int createSecureContainer(String id, int sizeMb, String fstype, String key, int ownerUid);
-
- /*
- * Finalize a container which has just been created and populated.
- * After finalization, the container is immutable.
- * Returns an int consistent with MountServiceResultCode
- */
- int finalizeSecureContainer(String id);
-
- /*
- * Destroy a secure container, and free up all resources associated with it.
- * NOTE: Ensure all references are released prior to deleting.
- * Returns an int consistent with MountServiceResultCode
- */
- int destroySecureContainer(String id, boolean force);
-
- /*
- * Mount a secure container with the specified key and owner UID.
- * Returns an int consistent with MountServiceResultCode
- */
- int mountSecureContainer(String id, String key, int ownerUid);
-
- /*
- * Unount a secure container.
- * Returns an int consistent with MountServiceResultCode
- */
- int unmountSecureContainer(String id, boolean force);
-
- /*
- * Returns true if the specified container is mounted
- */
- boolean isSecureContainerMounted(String id);
-
- /*
- * Rename an unmounted secure container.
- * Returns an int consistent with MountServiceResultCode
- */
- int renameSecureContainer(String oldId, String newId);
-
- /*
- * Returns the filesystem path of a mounted secure container.
- */
- String getSecureContainerPath(String id);
-
- /**
- * Gets an Array of currently known secure container IDs
- */
- String[] getSecureContainerList();
-
- /**
- * Shuts down the MountService and gracefully unmounts all external media.
- * Invokes call back once the shutdown is complete.
- */
- void shutdown(IMountShutdownObserver observer);
-
- /**
- * Call into MountService by PackageManager to notify that its done
- * processing the media status update request.
- */
- void finishMediaUpdate();
-
- /**
- * Mounts an Opaque Binary Blob (OBB) with the specified decryption key and only
- * allows the calling process's UID access to the contents.
- *
- * MountService will call back to the supplied IObbActionListener to inform
- * it of the terminal state of the call.
- */
- void mountObb(String filename, String key, IObbActionListener token);
-
- /**
- * Unmounts an Opaque Binary Blob (OBB). When the force flag is specified, any
- * program using it will be forcibly killed to unmount the image.
- *
- * MountService will call back to the supplied IObbActionListener to inform
- * it of the terminal state of the call.
- */
- void unmountObb(String filename, boolean force, IObbActionListener token);
-
- /**
- * Checks whether the specified Opaque Binary Blob (OBB) is mounted somewhere.
- */
- boolean isObbMounted(String filename);
-
- /**
- * Gets the path to the mounted Opaque Binary Blob (OBB).
- */
- String getMountedObbPath(String filename);
-}
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
new file mode 100644
index 0000000..60ea95c
--- /dev/null
+++ b/core/java/android/os/storage/IMountService.java
@@ -0,0 +1,1046 @@
+/*
+ * 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.os.storage;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.Parcel;
+import android.os.RemoteException;
+
+/**
+ * WARNING! Update IMountService.h and IMountService.cpp if you change this
+ * file. In particular, the ordering of the methods below must match the
+ * _TRANSACTION enum in IMountService.cpp
+ *
+ * @hide - Applications should use android.os.storage.StorageManager to access
+ * storage functions.
+ */
+public interface IMountService extends IInterface {
+ /** Local-side IPC implementation stub class. */
+ public static abstract class Stub extends Binder implements IMountService {
+ private static class Proxy implements IMountService {
+ private IBinder mRemote;
+
+ Proxy(IBinder remote) {
+ mRemote = remote;
+ }
+
+ public IBinder asBinder() {
+ return mRemote;
+ }
+
+ public String getInterfaceDescriptor() {
+ return DESCRIPTOR;
+ }
+
+ /**
+ * Registers an IMountServiceListener for receiving async
+ * notifications.
+ */
+ public void registerListener(IMountServiceListener listener) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeStrongBinder((listener != null ? listener.asBinder() : null));
+ mRemote.transact(Stub.TRANSACTION_registerListener, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ /**
+ * Unregisters an IMountServiceListener
+ */
+ public void unregisterListener(IMountServiceListener listener) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeStrongBinder((listener != null ? listener.asBinder() : null));
+ mRemote.transact(Stub.TRANSACTION_unregisterListener, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ /**
+ * Returns true if a USB mass storage host is connected
+ */
+ public boolean isUsbMassStorageConnected() throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ boolean _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ mRemote.transact(Stub.TRANSACTION_isUsbMassStorageConnected, _data, _reply, 0);
+ _reply.readException();
+ _result = 0 != _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /**
+ * Enables / disables USB mass storage. The caller should check
+ * actual status of enabling/disabling USB mass storage via
+ * StorageEventListener.
+ */
+ public void setUsbMassStorageEnabled(boolean enable) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt((enable ? 1 : 0));
+ mRemote.transact(Stub.TRANSACTION_setUsbMassStorageEnabled, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ /**
+ * Returns true if a USB mass storage host is enabled (media is
+ * shared)
+ */
+ public boolean isUsbMassStorageEnabled() throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ boolean _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ mRemote.transact(Stub.TRANSACTION_isUsbMassStorageEnabled, _data, _reply, 0);
+ _reply.readException();
+ _result = 0 != _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /**
+ * Mount external storage at given mount point. Returns an int
+ * consistent with MountServiceResultCode
+ */
+ public int mountVolume(String mountPoint) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(mountPoint);
+ mRemote.transact(Stub.TRANSACTION_mountVolume, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /**
+ * Safely unmount external storage at given mount point. The unmount
+ * is an asynchronous operation. Applications should register
+ * StorageEventListener for storage related status changes.
+ */
+ public void unmountVolume(String mountPoint, boolean force) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(mountPoint);
+ _data.writeInt((force ? 1 : 0));
+ mRemote.transact(Stub.TRANSACTION_unmountVolume, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ /**
+ * Format external storage given a mount point. Returns an int
+ * consistent with MountServiceResultCode
+ */
+ public int formatVolume(String mountPoint) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(mountPoint);
+ mRemote.transact(Stub.TRANSACTION_formatVolume, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /**
+ * Returns an array of pids with open files on the specified path.
+ */
+ public int[] getStorageUsers(String path) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int[] _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(path);
+ mRemote.transact(Stub.TRANSACTION_getStorageUsers, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.createIntArray();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /**
+ * Gets the state of a volume via its mountpoint.
+ */
+ public String getVolumeState(String mountPoint) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ String _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(mountPoint);
+ mRemote.transact(Stub.TRANSACTION_getVolumeState, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readString();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /*
+ * Creates a secure container with the specified parameters. Returns
+ * an int consistent with MountServiceResultCode
+ */
+ public int createSecureContainer(String id, int sizeMb, String fstype, String key,
+ int ownerUid) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(id);
+ _data.writeInt(sizeMb);
+ _data.writeString(fstype);
+ _data.writeString(key);
+ _data.writeInt(ownerUid);
+ mRemote.transact(Stub.TRANSACTION_createSecureContainer, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /*
+ * Destroy a secure container, and free up all resources associated
+ * with it. NOTE: Ensure all references are released prior to
+ * deleting. Returns an int consistent with MountServiceResultCode
+ */
+ public int destroySecureContainer(String id, boolean force) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(id);
+ _data.writeInt((force ? 1 : 0));
+ mRemote.transact(Stub.TRANSACTION_destroySecureContainer, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /*
+ * Finalize a container which has just been created and populated.
+ * After finalization, the container is immutable. Returns an int
+ * consistent with MountServiceResultCode
+ */
+ public int finalizeSecureContainer(String id) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(id);
+ mRemote.transact(Stub.TRANSACTION_finalizeSecureContainer, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /*
+ * Mount a secure container with the specified key and owner UID.
+ * Returns an int consistent with MountServiceResultCode
+ */
+ public int mountSecureContainer(String id, String key, int ownerUid)
+ throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(id);
+ _data.writeString(key);
+ _data.writeInt(ownerUid);
+ mRemote.transact(Stub.TRANSACTION_mountSecureContainer, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /*
+ * Unount a secure container. Returns an int consistent with
+ * MountServiceResultCode
+ */
+ public int unmountSecureContainer(String id, boolean force) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(id);
+ _data.writeInt((force ? 1 : 0));
+ mRemote.transact(Stub.TRANSACTION_unmountSecureContainer, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /*
+ * Returns true if the specified container is mounted
+ */
+ public boolean isSecureContainerMounted(String id) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ boolean _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(id);
+ mRemote.transact(Stub.TRANSACTION_isSecureContainerMounted, _data, _reply, 0);
+ _reply.readException();
+ _result = 0 != _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /*
+ * Rename an unmounted secure container. Returns an int consistent
+ * with MountServiceResultCode
+ */
+ public int renameSecureContainer(String oldId, String newId) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(oldId);
+ _data.writeString(newId);
+ mRemote.transact(Stub.TRANSACTION_renameSecureContainer, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /*
+ * Returns the filesystem path of a mounted secure container.
+ */
+ public String getSecureContainerPath(String id) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ String _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(id);
+ mRemote.transact(Stub.TRANSACTION_getSecureContainerPath, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readString();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /**
+ * Gets an Array of currently known secure container IDs
+ */
+ public String[] getSecureContainerList() throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ String[] _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ mRemote.transact(Stub.TRANSACTION_getSecureContainerList, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.createStringArray();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /**
+ * Shuts down the MountService and gracefully unmounts all external
+ * media. Invokes call back once the shutdown is complete.
+ */
+ public void shutdown(IMountShutdownObserver observer)
+ throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeStrongBinder((observer != null ? observer.asBinder() : null));
+ mRemote.transact(Stub.TRANSACTION_shutdown, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ /**
+ * Call into MountService by PackageManager to notify that its done
+ * processing the media status update request.
+ */
+ public void finishMediaUpdate() throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ mRemote.transact(Stub.TRANSACTION_finishMediaUpdate, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ /**
+ * Mounts an Opaque Binary Blob (OBB) with the specified decryption
+ * key and only allows the calling process's UID access to the
+ * contents. MountService will call back to the supplied
+ * IObbActionListener to inform it of the terminal state of the
+ * call.
+ */
+ public void mountObb(String filename, String key, IObbActionListener token)
+ throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(filename);
+ _data.writeString(key);
+ _data.writeStrongBinder((token != null ? token.asBinder() : null));
+ mRemote.transact(Stub.TRANSACTION_mountObb, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ /**
+ * Unmounts an Opaque Binary Blob (OBB). When the force flag is
+ * specified, any program using it will be forcibly killed to
+ * unmount the image. MountService will call back to the supplied
+ * IObbActionListener to inform it of the terminal state of the
+ * call.
+ */
+ public void unmountObb(String filename, boolean force, IObbActionListener token)
+ throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(filename);
+ _data.writeInt((force ? 1 : 0));
+ _data.writeStrongBinder((token != null ? token.asBinder() : null));
+ mRemote.transact(Stub.TRANSACTION_unmountObb, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ /**
+ * Checks whether the specified Opaque Binary Blob (OBB) is mounted
+ * somewhere.
+ */
+ public boolean isObbMounted(String filename) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ boolean _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(filename);
+ mRemote.transact(Stub.TRANSACTION_isObbMounted, _data, _reply, 0);
+ _reply.readException();
+ _result = 0 != _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ /**
+ * Gets the path to the mounted Opaque Binary Blob (OBB).
+ */
+ public String getMountedObbPath(String filename) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ String _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(filename);
+ mRemote.transact(Stub.TRANSACTION_getMountedObbPath, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readString();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+ }
+
+ private static final String DESCRIPTOR = "IMountService";
+
+ static final int TRANSACTION_registerListener = IBinder.FIRST_CALL_TRANSACTION + 0;
+
+ static final int TRANSACTION_unregisterListener = IBinder.FIRST_CALL_TRANSACTION + 1;
+
+ static final int TRANSACTION_isUsbMassStorageConnected = IBinder.FIRST_CALL_TRANSACTION + 2;
+
+ static final int TRANSACTION_setUsbMassStorageEnabled = IBinder.FIRST_CALL_TRANSACTION + 3;
+
+ static final int TRANSACTION_isUsbMassStorageEnabled = IBinder.FIRST_CALL_TRANSACTION + 4;
+
+ static final int TRANSACTION_mountVolume = IBinder.FIRST_CALL_TRANSACTION + 5;
+
+ static final int TRANSACTION_unmountVolume = IBinder.FIRST_CALL_TRANSACTION + 6;
+
+ static final int TRANSACTION_formatVolume = IBinder.FIRST_CALL_TRANSACTION + 7;
+
+ static final int TRANSACTION_getStorageUsers = IBinder.FIRST_CALL_TRANSACTION + 8;
+
+ static final int TRANSACTION_getVolumeState = IBinder.FIRST_CALL_TRANSACTION + 9;
+
+ static final int TRANSACTION_createSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 10;
+
+ static final int TRANSACTION_finalizeSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 11;
+
+ static final int TRANSACTION_destroySecureContainer = IBinder.FIRST_CALL_TRANSACTION + 12;
+
+ static final int TRANSACTION_mountSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 13;
+
+ static final int TRANSACTION_unmountSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 14;
+
+ static final int TRANSACTION_isSecureContainerMounted = IBinder.FIRST_CALL_TRANSACTION + 15;
+
+ static final int TRANSACTION_renameSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 16;
+
+ static final int TRANSACTION_getSecureContainerPath = IBinder.FIRST_CALL_TRANSACTION + 17;
+
+ static final int TRANSACTION_getSecureContainerList = IBinder.FIRST_CALL_TRANSACTION + 18;
+
+ static final int TRANSACTION_shutdown = IBinder.FIRST_CALL_TRANSACTION + 19;
+
+ static final int TRANSACTION_finishMediaUpdate = IBinder.FIRST_CALL_TRANSACTION + 20;
+
+ static final int TRANSACTION_mountObb = IBinder.FIRST_CALL_TRANSACTION + 21;
+
+ static final int TRANSACTION_unmountObb = IBinder.FIRST_CALL_TRANSACTION + 22;
+
+ static final int TRANSACTION_isObbMounted = IBinder.FIRST_CALL_TRANSACTION + 23;
+
+ static final int TRANSACTION_getMountedObbPath = IBinder.FIRST_CALL_TRANSACTION + 24;
+
+ /**
+ * Cast an IBinder object into an IMountService interface, generating a
+ * proxy if needed.
+ */
+ public static IMountService asInterface(IBinder obj) {
+ if (obj == null) {
+ return null;
+ }
+ IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+ if (iin != null && iin instanceof IMountService) {
+ return (IMountService) iin;
+ }
+ return new IMountService.Stub.Proxy(obj);
+ }
+
+ /** Construct the stub at attach it to the interface. */
+ public Stub() {
+ attachInterface(this, DESCRIPTOR);
+ }
+
+ public IBinder asBinder() {
+ return this;
+ }
+
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply,
+ int flags) throws RemoteException {
+ switch (code) {
+ case INTERFACE_TRANSACTION: {
+ reply.writeString(DESCRIPTOR);
+ return true;
+ }
+ case TRANSACTION_registerListener: {
+ data.enforceInterface(DESCRIPTOR);
+ IMountServiceListener listener;
+ listener = IMountServiceListener.Stub.asInterface(data.readStrongBinder());
+ registerListener(listener);
+ reply.writeNoException();
+ return true;
+ }
+ case TRANSACTION_unregisterListener: {
+ data.enforceInterface(DESCRIPTOR);
+ IMountServiceListener listener;
+ listener = IMountServiceListener.Stub.asInterface(data.readStrongBinder());
+ unregisterListener(listener);
+ reply.writeNoException();
+ return true;
+ }
+ case TRANSACTION_isUsbMassStorageConnected: {
+ data.enforceInterface(DESCRIPTOR);
+ boolean result = isUsbMassStorageConnected();
+ reply.writeNoException();
+ reply.writeInt((result ? 1 : 0));
+ return true;
+ }
+ case TRANSACTION_setUsbMassStorageEnabled: {
+ data.enforceInterface(DESCRIPTOR);
+ boolean enable;
+ enable = 0 != data.readInt();
+ setUsbMassStorageEnabled(enable);
+ reply.writeNoException();
+ return true;
+ }
+ case TRANSACTION_isUsbMassStorageEnabled: {
+ data.enforceInterface(DESCRIPTOR);
+ boolean result = isUsbMassStorageEnabled();
+ reply.writeNoException();
+ reply.writeInt((result ? 1 : 0));
+ return true;
+ }
+ case TRANSACTION_mountVolume: {
+ data.enforceInterface(DESCRIPTOR);
+ String mountPoint;
+ mountPoint = data.readString();
+ int resultCode = mountVolume(mountPoint);
+ reply.writeNoException();
+ reply.writeInt(resultCode);
+ return true;
+ }
+ case TRANSACTION_unmountVolume: {
+ data.enforceInterface(DESCRIPTOR);
+ String mountPoint;
+ mountPoint = data.readString();
+ boolean force;
+ force = 0 != data.readInt();
+ unmountVolume(mountPoint, force);
+ reply.writeNoException();
+ return true;
+ }
+ case TRANSACTION_formatVolume: {
+ data.enforceInterface(DESCRIPTOR);
+ String mountPoint;
+ mountPoint = data.readString();
+ int result = formatVolume(mountPoint);
+ reply.writeNoException();
+ reply.writeInt(result);
+ return true;
+ }
+ case TRANSACTION_getStorageUsers: {
+ data.enforceInterface(DESCRIPTOR);
+ String path;
+ path = data.readString();
+ int[] pids = getStorageUsers(path);
+ reply.writeNoException();
+ reply.writeIntArray(pids);
+ return true;
+ }
+ case TRANSACTION_getVolumeState: {
+ data.enforceInterface(DESCRIPTOR);
+ String mountPoint;
+ mountPoint = data.readString();
+ String state = getVolumeState(mountPoint);
+ reply.writeNoException();
+ reply.writeString(state);
+ return true;
+ }
+ case TRANSACTION_createSecureContainer: {
+ data.enforceInterface(DESCRIPTOR);
+ String id;
+ id = data.readString();
+ int sizeMb;
+ sizeMb = data.readInt();
+ String fstype;
+ fstype = data.readString();
+ String key;
+ key = data.readString();
+ int ownerUid;
+ ownerUid = data.readInt();
+ int resultCode = createSecureContainer(id, sizeMb, fstype, key, ownerUid);
+ reply.writeNoException();
+ reply.writeInt(resultCode);
+ return true;
+ }
+ case TRANSACTION_finalizeSecureContainer: {
+ data.enforceInterface(DESCRIPTOR);
+ String id;
+ id = data.readString();
+ int resultCode = finalizeSecureContainer(id);
+ reply.writeNoException();
+ reply.writeInt(resultCode);
+ return true;
+ }
+ case TRANSACTION_destroySecureContainer: {
+ data.enforceInterface(DESCRIPTOR);
+ String id;
+ id = data.readString();
+ boolean force;
+ force = 0 != data.readInt();
+ int resultCode = destroySecureContainer(id, force);
+ reply.writeNoException();
+ reply.writeInt(resultCode);
+ return true;
+ }
+ case TRANSACTION_mountSecureContainer: {
+ data.enforceInterface(DESCRIPTOR);
+ String id;
+ id = data.readString();
+ String key;
+ key = data.readString();
+ int ownerUid;
+ ownerUid = data.readInt();
+ int resultCode = mountSecureContainer(id, key, ownerUid);
+ reply.writeNoException();
+ reply.writeInt(resultCode);
+ return true;
+ }
+ case TRANSACTION_unmountSecureContainer: {
+ data.enforceInterface(DESCRIPTOR);
+ String id;
+ id = data.readString();
+ boolean force;
+ force = 0 != data.readInt();
+ int resultCode = unmountSecureContainer(id, force);
+ reply.writeNoException();
+ reply.writeInt(resultCode);
+ return true;
+ }
+ case TRANSACTION_isSecureContainerMounted: {
+ data.enforceInterface(DESCRIPTOR);
+ String id;
+ id = data.readString();
+ boolean status = isSecureContainerMounted(id);
+ reply.writeNoException();
+ reply.writeInt((status ? 1 : 0));
+ return true;
+ }
+ case TRANSACTION_renameSecureContainer: {
+ data.enforceInterface(DESCRIPTOR);
+ String oldId;
+ oldId = data.readString();
+ String newId;
+ newId = data.readString();
+ int resultCode = renameSecureContainer(oldId, newId);
+ reply.writeNoException();
+ reply.writeInt(resultCode);
+ return true;
+ }
+ case TRANSACTION_getSecureContainerPath: {
+ data.enforceInterface(DESCRIPTOR);
+ String id;
+ id = data.readString();
+ String path = getSecureContainerPath(id);
+ reply.writeNoException();
+ reply.writeString(path);
+ return true;
+ }
+ case TRANSACTION_getSecureContainerList: {
+ data.enforceInterface(DESCRIPTOR);
+ String[] ids = getSecureContainerList();
+ reply.writeNoException();
+ reply.writeStringArray(ids);
+ return true;
+ }
+ case TRANSACTION_shutdown: {
+ data.enforceInterface(DESCRIPTOR);
+ IMountShutdownObserver observer;
+ observer = IMountShutdownObserver.Stub.asInterface(data
+ .readStrongBinder());
+ shutdown(observer);
+ reply.writeNoException();
+ return true;
+ }
+ case TRANSACTION_finishMediaUpdate: {
+ data.enforceInterface(DESCRIPTOR);
+ finishMediaUpdate();
+ reply.writeNoException();
+ return true;
+ }
+ case TRANSACTION_mountObb: {
+ data.enforceInterface(DESCRIPTOR);
+ String filename;
+ filename = data.readString();
+ String key;
+ key = data.readString();
+ IObbActionListener observer;
+ observer = IObbActionListener.Stub.asInterface(data.readStrongBinder());
+ mountObb(filename, key, observer);
+ reply.writeNoException();
+ return true;
+ }
+ case TRANSACTION_unmountObb: {
+ data.enforceInterface(DESCRIPTOR);
+ String filename;
+ filename = data.readString();
+ boolean force;
+ force = 0 != data.readInt();
+ IObbActionListener observer;
+ observer = IObbActionListener.Stub.asInterface(data.readStrongBinder());
+ unmountObb(filename, force, observer);
+ reply.writeNoException();
+ return true;
+ }
+ case TRANSACTION_isObbMounted: {
+ data.enforceInterface(DESCRIPTOR);
+ String filename;
+ filename = data.readString();
+ boolean status = isObbMounted(filename);
+ reply.writeNoException();
+ reply.writeInt((status ? 1 : 0));
+ return true;
+ }
+ case TRANSACTION_getMountedObbPath: {
+ data.enforceInterface(DESCRIPTOR);
+ String filename;
+ filename = data.readString();
+ String mountedPath = getMountedObbPath(filename);
+ reply.writeNoException();
+ reply.writeString(mountedPath);
+ return true;
+ }
+ }
+ return super.onTransact(code, data, reply, flags);
+ }
+ }
+
+ /*
+ * Creates a secure container with the specified parameters. Returns an int
+ * consistent with MountServiceResultCode
+ */
+ public int createSecureContainer(String id, int sizeMb, String fstype, String key, int ownerUid)
+ throws RemoteException;
+
+ /*
+ * Destroy a secure container, and free up all resources associated with it.
+ * NOTE: Ensure all references are released prior to deleting. Returns an
+ * int consistent with MountServiceResultCode
+ */
+ public int destroySecureContainer(String id, boolean force) throws RemoteException;
+
+ /*
+ * Finalize a container which has just been created and populated. After
+ * finalization, the container is immutable. Returns an int consistent with
+ * MountServiceResultCode
+ */
+ public int finalizeSecureContainer(String id) throws RemoteException;
+
+ /**
+ * Call into MountService by PackageManager to notify that its done
+ * processing the media status update request.
+ */
+ public void finishMediaUpdate() throws RemoteException;
+
+ /**
+ * Format external storage given a mount point. Returns an int consistent
+ * with MountServiceResultCode
+ */
+ public int formatVolume(String mountPoint) throws RemoteException;
+
+ /**
+ * Gets the path to the mounted Opaque Binary Blob (OBB).
+ */
+ public String getMountedObbPath(String filename) throws RemoteException;
+
+ /**
+ * Gets an Array of currently known secure container IDs
+ */
+ public String[] getSecureContainerList() throws RemoteException;
+
+ /*
+ * Returns the filesystem path of a mounted secure container.
+ */
+ public String getSecureContainerPath(String id) throws RemoteException;
+
+ /**
+ * Returns an array of pids with open files on the specified path.
+ */
+ public int[] getStorageUsers(String path) throws RemoteException;
+
+ /**
+ * Gets the state of a volume via its mountpoint.
+ */
+ public String getVolumeState(String mountPoint) throws RemoteException;
+
+ /**
+ * Checks whether the specified Opaque Binary Blob (OBB) is mounted
+ * somewhere.
+ */
+ public boolean isObbMounted(String filename) throws RemoteException;
+
+ /*
+ * Returns true if the specified container is mounted
+ */
+ public boolean isSecureContainerMounted(String id) throws RemoteException;
+
+ /**
+ * Returns true if a USB mass storage host is connected
+ */
+ public boolean isUsbMassStorageConnected() throws RemoteException;
+
+ /**
+ * Returns true if a USB mass storage host is enabled (media is shared)
+ */
+ public boolean isUsbMassStorageEnabled() throws RemoteException;
+
+ /**
+ * Mounts an Opaque Binary Blob (OBB) with the specified decryption key and
+ * only allows the calling process's UID access to the contents.
+ * MountService will call back to the supplied IObbActionListener to inform
+ * it of the terminal state of the call.
+ */
+ public void mountObb(String filename, String key, IObbActionListener token)
+ throws RemoteException;
+
+ /*
+ * Mount a secure container with the specified key and owner UID. Returns an
+ * int consistent with MountServiceResultCode
+ */
+ public int mountSecureContainer(String id, String key, int ownerUid) throws RemoteException;
+
+ /**
+ * Mount external storage at given mount point. Returns an int consistent
+ * with MountServiceResultCode
+ */
+ public int mountVolume(String mountPoint) throws RemoteException;
+
+ /**
+ * Registers an IMountServiceListener for receiving async notifications.
+ */
+ public void registerListener(IMountServiceListener listener) throws RemoteException;
+
+ /*
+ * Rename an unmounted secure container. Returns an int consistent with
+ * MountServiceResultCode
+ */
+ public int renameSecureContainer(String oldId, String newId) throws RemoteException;
+
+ /**
+ * Enables / disables USB mass storage. The caller should check actual
+ * status of enabling/disabling USB mass storage via StorageEventListener.
+ */
+ public void setUsbMassStorageEnabled(boolean enable) throws RemoteException;
+
+ /**
+ * Shuts down the MountService and gracefully unmounts all external media.
+ * Invokes call back once the shutdown is complete.
+ */
+ public void shutdown(IMountShutdownObserver observer) throws RemoteException;
+
+ /**
+ * Unmounts an Opaque Binary Blob (OBB). When the force flag is specified,
+ * any program using it will be forcibly killed to unmount the image.
+ * MountService will call back to the supplied IObbActionListener to inform
+ * it of the terminal state of the call.
+ */
+ public void unmountObb(String filename, boolean force, IObbActionListener token)
+ throws RemoteException;
+
+ /*
+ * Unount a secure container. Returns an int consistent with
+ * MountServiceResultCode
+ */
+ public int unmountSecureContainer(String id, boolean force) throws RemoteException;
+
+ /**
+ * Safely unmount external storage at given mount point. The unmount is an
+ * asynchronous operation. Applications should register StorageEventListener
+ * for storage related status changes.
+ */
+ public void unmountVolume(String mountPoint, boolean force) throws RemoteException;
+
+ /**
+ * Unregisters an IMountServiceListener
+ */
+ public void unregisterListener(IMountServiceListener listener) throws RemoteException;
+}
diff --git a/core/java/android/os/storage/IMountServiceListener.aidl b/core/java/android/os/storage/IMountServiceListener.aidl
deleted file mode 100644
index 883413a..0000000
--- a/core/java/android/os/storage/IMountServiceListener.aidl
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os.storage;
-
-/**
- * Callback class for receiving events from MountService.
- *
- * @hide - Applications should use android.os.storage.IStorageEventListener
- * for storage event callbacks.
- */
-interface IMountServiceListener {
- /**
- * Detection state of USB Mass Storage has changed
- *
- * @param available true if a UMS host is connected.
- */
- void onUsbMassStorageConnectionChanged(boolean connected);
-
- /**
- * Storage state has changed.
- *
- * @param path The volume mount path.
- * @param oldState The old state of the volume.
- * @param newState The new state of the volume.
- *
- * Note: State is one of the values returned by Environment.getExternalStorageState()
- */
- void onStorageStateChanged(String path, String oldState, String newState);
-}
diff --git a/core/java/android/os/storage/IMountServiceListener.java b/core/java/android/os/storage/IMountServiceListener.java
new file mode 100644
index 0000000..d5c5fa5
--- /dev/null
+++ b/core/java/android/os/storage/IMountServiceListener.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.Parcel;
+import android.os.RemoteException;
+
+/**
+ * Callback class for receiving events from MountService.
+ *
+ * @hide - Applications should use IStorageEventListener for storage event
+ * callbacks.
+ */
+public interface IMountServiceListener extends IInterface {
+ /** Local-side IPC implementation stub class. */
+ public static abstract class Stub extends Binder implements IMountServiceListener {
+ private static final String DESCRIPTOR = "IMountServiceListener";
+
+ /** Construct the stub at attach it to the interface. */
+ public Stub() {
+ this.attachInterface(this, DESCRIPTOR);
+ }
+
+ /**
+ * Cast an IBinder object into an IMountServiceListener interface,
+ * generating a proxy if needed.
+ */
+ public static IMountServiceListener asInterface(IBinder obj) {
+ if ((obj == null)) {
+ return null;
+ }
+ IInterface iin = (IInterface) obj.queryLocalInterface(DESCRIPTOR);
+ if (((iin != null) && (iin instanceof IMountServiceListener))) {
+ return ((IMountServiceListener) iin);
+ }
+ return new IMountServiceListener.Stub.Proxy(obj);
+ }
+
+ public IBinder asBinder() {
+ return this;
+ }
+
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ switch (code) {
+ case INTERFACE_TRANSACTION: {
+ reply.writeString(DESCRIPTOR);
+ return true;
+ }
+ case TRANSACTION_onUsbMassStorageConnectionChanged: {
+ data.enforceInterface(DESCRIPTOR);
+ boolean connected;
+ connected = (0 != data.readInt());
+ this.onUsbMassStorageConnectionChanged(connected);
+ reply.writeNoException();
+ return true;
+ }
+ case TRANSACTION_onStorageStateChanged: {
+ data.enforceInterface(DESCRIPTOR);
+ String path;
+ path = data.readString();
+ String oldState;
+ oldState = data.readString();
+ String newState;
+ newState = data.readString();
+ this.onStorageStateChanged(path, oldState, newState);
+ reply.writeNoException();
+ return true;
+ }
+ }
+ return super.onTransact(code, data, reply, flags);
+ }
+
+ private static class Proxy implements IMountServiceListener {
+ private IBinder mRemote;
+
+ Proxy(IBinder remote) {
+ mRemote = remote;
+ }
+
+ public IBinder asBinder() {
+ return mRemote;
+ }
+
+ public String getInterfaceDescriptor() {
+ return DESCRIPTOR;
+ }
+
+ /**
+ * Detection state of USB Mass Storage has changed
+ *
+ * @param available true if a UMS host is connected.
+ */
+ public void onUsbMassStorageConnectionChanged(boolean connected) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt(((connected) ? (1) : (0)));
+ mRemote.transact(Stub.TRANSACTION_onUsbMassStorageConnectionChanged, _data,
+ _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ /**
+ * Storage state has changed.
+ *
+ * @param path The volume mount path.
+ * @param oldState The old state of the volume.
+ * @param newState The new state of the volume. Note: State is one
+ * of the values returned by
+ * Environment.getExternalStorageState()
+ */
+ public void onStorageStateChanged(String path, String oldState, String newState)
+ throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(path);
+ _data.writeString(oldState);
+ _data.writeString(newState);
+ mRemote.transact(Stub.TRANSACTION_onStorageStateChanged, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+ }
+
+ static final int TRANSACTION_onUsbMassStorageConnectionChanged = (IBinder.FIRST_CALL_TRANSACTION + 0);
+
+ static final int TRANSACTION_onStorageStateChanged = (IBinder.FIRST_CALL_TRANSACTION + 1);
+ }
+
+ /**
+ * Detection state of USB Mass Storage has changed
+ *
+ * @param available true if a UMS host is connected.
+ */
+ public void onUsbMassStorageConnectionChanged(boolean connected) throws RemoteException;
+
+ /**
+ * Storage state has changed.
+ *
+ * @param path The volume mount path.
+ * @param oldState The old state of the volume.
+ * @param newState The new state of the volume. Note: State is one of the
+ * values returned by Environment.getExternalStorageState()
+ */
+ public void onStorageStateChanged(String path, String oldState, String newState)
+ throws RemoteException;
+}
diff --git a/core/java/android/os/storage/IMountShutdownObserver.aidl b/core/java/android/os/storage/IMountShutdownObserver.aidl
deleted file mode 100644
index 0aa8a45..0000000
--- a/core/java/android/os/storage/IMountShutdownObserver.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os.storage;
-
-/**
- * Callback class for receiving events related
- * to shutdown.
- *
- * @hide - For internal consumption only.
- */
-interface IMountShutdownObserver {
- /**
- * This method is called when the shutdown
- * of MountService completed.
- * @param statusCode indicates success or failure
- * of the shutdown.
- */
- void onShutDownComplete(int statusCode);
-}
diff --git a/core/java/android/os/storage/IMountShutdownObserver.java b/core/java/android/os/storage/IMountShutdownObserver.java
new file mode 100644
index 0000000..d946e1a
--- /dev/null
+++ b/core/java/android/os/storage/IMountShutdownObserver.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.Parcel;
+import android.os.RemoteException;
+
+/**
+ * Callback class for receiving events related to shutdown.
+ *
+ * @hide - For internal consumption only.
+ */
+public interface IMountShutdownObserver extends IInterface {
+ /** Local-side IPC implementation stub class. */
+ public static abstract class Stub extends Binder implements IMountShutdownObserver {
+ private static final java.lang.String DESCRIPTOR = "IMountShutdownObserver";
+
+ /** Construct the stub at attach it to the interface. */
+ public Stub() {
+ this.attachInterface(this, DESCRIPTOR);
+ }
+
+ /**
+ * Cast an IBinder object into an IMountShutdownObserver interface,
+ * generating a proxy if needed.
+ */
+ public static IMountShutdownObserver asInterface(IBinder obj) {
+ if ((obj == null)) {
+ return null;
+ }
+ IInterface iin = (IInterface) obj.queryLocalInterface(DESCRIPTOR);
+ if (((iin != null) && (iin instanceof IMountShutdownObserver))) {
+ return ((IMountShutdownObserver) iin);
+ }
+ return new IMountShutdownObserver.Stub.Proxy(obj);
+ }
+
+ public IBinder asBinder() {
+ return this;
+ }
+
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ switch (code) {
+ case INTERFACE_TRANSACTION: {
+ reply.writeString(DESCRIPTOR);
+ return true;
+ }
+ case TRANSACTION_onShutDownComplete: {
+ data.enforceInterface(DESCRIPTOR);
+ int statusCode;
+ statusCode = data.readInt();
+ this.onShutDownComplete(statusCode);
+ reply.writeNoException();
+ return true;
+ }
+ }
+ return super.onTransact(code, data, reply, flags);
+ }
+
+ private static class Proxy implements IMountShutdownObserver {
+ private IBinder mRemote;
+
+ Proxy(IBinder remote) {
+ mRemote = remote;
+ }
+
+ public IBinder asBinder() {
+ return mRemote;
+ }
+
+ public java.lang.String getInterfaceDescriptor() {
+ return DESCRIPTOR;
+ }
+
+ /**
+ * This method is called when the shutdown of MountService
+ * completed.
+ *
+ * @param statusCode indicates success or failure of the shutdown.
+ */
+ public void onShutDownComplete(int statusCode) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt(statusCode);
+ mRemote.transact(Stub.TRANSACTION_onShutDownComplete, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+ }
+
+ static final int TRANSACTION_onShutDownComplete = (IBinder.FIRST_CALL_TRANSACTION + 0);
+ }
+
+ /**
+ * This method is called when the shutdown of MountService completed.
+ *
+ * @param statusCode indicates success or failure of the shutdown.
+ */
+ public void onShutDownComplete(int statusCode) throws RemoteException;
+}
diff --git a/core/java/android/os/storage/IObbActionListener.aidl b/core/java/android/os/storage/IObbActionListener.aidl
deleted file mode 100644
index 78d7a9e..0000000
--- a/core/java/android/os/storage/IObbActionListener.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.os.storage;
-
-/**
- * Callback class for receiving events from MountService about
- * Opaque Binary Blobs (OBBs).
- *
- * @hide - Applications should use android.os.storage.StorageManager
- * to interact with OBBs.
- */
-interface IObbActionListener {
- /**
- * Return from an OBB action result.
- *
- * @param filename the path to the OBB the operation was performed on
- * @param returnCode status of the operation
- */
- void onObbResult(String filename, String status);
-}
diff --git a/core/java/android/os/storage/IObbActionListener.java b/core/java/android/os/storage/IObbActionListener.java
new file mode 100644
index 0000000..2c098ac
--- /dev/null
+++ b/core/java/android/os/storage/IObbActionListener.java
@@ -0,0 +1,130 @@
+/*
+ * 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.os.storage;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.Parcel;
+import android.os.RemoteException;
+
+/**
+ * Callback class for receiving events from MountService about Opaque Binary
+ * Blobs (OBBs).
+ *
+ * @hide - Applications should use StorageManager to interact with OBBs.
+ */
+public interface IObbActionListener extends IInterface {
+ /** Local-side IPC implementation stub class. */
+ public static abstract class Stub extends Binder implements IObbActionListener {
+ private static final String DESCRIPTOR = "IObbActionListener";
+
+ /** Construct the stub at attach it to the interface. */
+ public Stub() {
+ this.attachInterface(this, DESCRIPTOR);
+ }
+
+ /**
+ * Cast an IBinder object into an IObbActionListener interface,
+ * generating a proxy if needed.
+ */
+ public static IObbActionListener asInterface(IBinder obj) {
+ if ((obj == null)) {
+ return null;
+ }
+ IInterface iin = (IInterface) obj.queryLocalInterface(DESCRIPTOR);
+ if (((iin != null) && (iin instanceof IObbActionListener))) {
+ return ((IObbActionListener) iin);
+ }
+ return new IObbActionListener.Stub.Proxy(obj);
+ }
+
+ public IBinder asBinder() {
+ return this;
+ }
+
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ switch (code) {
+ case INTERFACE_TRANSACTION: {
+ reply.writeString(DESCRIPTOR);
+ return true;
+ }
+ case TRANSACTION_onObbResult: {
+ data.enforceInterface(DESCRIPTOR);
+ String filename;
+ filename = data.readString();
+ String status;
+ status = data.readString();
+ this.onObbResult(filename, status);
+ reply.writeNoException();
+ return true;
+ }
+ }
+ return super.onTransact(code, data, reply, flags);
+ }
+
+ private static class Proxy implements IObbActionListener {
+ private IBinder mRemote;
+
+ Proxy(IBinder remote) {
+ mRemote = remote;
+ }
+
+ public IBinder asBinder() {
+ return mRemote;
+ }
+
+ public String getInterfaceDescriptor() {
+ return DESCRIPTOR;
+ }
+
+ /**
+ * Return from an OBB action result.
+ *
+ * @param filename the path to the OBB the operation was performed
+ * on
+ * @param returnCode status of the operation
+ */
+ public void onObbResult(String filename, String status) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(filename);
+ _data.writeString(status);
+ mRemote.transact(Stub.TRANSACTION_onObbResult, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+ }
+
+ static final int TRANSACTION_onObbResult = (IBinder.FIRST_CALL_TRANSACTION + 0);
+ }
+
+ /**
+ * Return from an OBB action result.
+ *
+ * @param filename the path to the OBB the operation was performed on
+ * @param returnCode status of the operation
+ */
+ public void onObbResult(String filename, String status) throws RemoteException;
+}
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 9948060..3861ef5 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -644,7 +644,7 @@
} else {
Log.i(TAG, "Rejecting incoming HID connection from " + address);
}
- } else if (BluetoothUuid.isNAP(uuid)){
+ } else if (BluetoothUuid.isBnep(uuid) || BluetoothUuid.isNap(uuid)){
authorized = true;
} else {
Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address);
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index 79a0c37..3fe14f9 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -287,8 +287,7 @@
// Offset the current touch position (from controller to cursor)
final float x = event.getX() + mCursorController.getOffsetX();
final float y = event.getY() + mCursorController.getOffsetY();
- int offset = widget.getOffset((int) x, (int) y);
- mCursorController.updatePosition(offset);
+ mCursorController.updatePosition((int) x, (int) y);
return true;
case MotionEvent.ACTION_UP:
@@ -320,25 +319,9 @@
public void onTakeFocus(TextView view, Spannable text, int dir) {
if ((dir & (View.FOCUS_FORWARD | View.FOCUS_DOWN)) != 0) {
- Layout layout = view.getLayout();
-
- if (layout == null) {
- /*
- * This shouldn't be null, but do something sensible if it is.
- */
+ if (view.getLayout() == null) {
+ // This shouldn't be null, but do something sensible if it is.
Selection.setSelection(text, text.length());
- } else {
- /*
- * Put the cursor at the end of the first line, which is
- * either the last offset if there is only one line, or the
- * offset before the first character of the second line
- * if there is more than one line.
- */
- if (layout.getLineCount() == 1) {
- Selection.setSelection(text, text.length());
- } else {
- Selection.setSelection(text, layout.getLineStart(1) - 1);
- }
}
} else {
Selection.setSelection(text, text.length());
diff --git a/core/java/android/util/TimingLogger.java b/core/java/android/util/TimingLogger.java
index 0f39c97..be442da 100644
--- a/core/java/android/util/TimingLogger.java
+++ b/core/java/android/util/TimingLogger.java
@@ -24,22 +24,26 @@
* A utility class to help log timings splits throughout a method call.
* Typical usage is:
*
- * TimingLogger timings = new TimingLogger(TAG, "methodA");
- * ... do some work A ...
- * timings.addSplit("work A");
- * ... do some work B ...
- * timings.addSplit("work B");
- * ... do some work C ...
- * timings.addSplit("work C");
- * timings.dumpToLog();
+ * <pre>
+ * TimingLogger timings = new TimingLogger(TAG, "methodA");
+ * // ... do some work A ...
+ * timings.addSplit("work A");
+ * // ... do some work B ...
+ * timings.addSplit("work B");
+ * // ... do some work C ...
+ * timings.addSplit("work C");
+ * timings.dumpToLog();
+ * </pre>
*
- * The dumpToLog call would add the following to the log:
+ * <p>The dumpToLog call would add the following to the log:</p>
*
- * D/TAG ( 3459): methodA: begin
- * D/TAG ( 3459): methodA: 9 ms, work A
- * D/TAG ( 3459): methodA: 1 ms, work B
- * D/TAG ( 3459): methodA: 6 ms, work C
- * D/TAG ( 3459): methodA: end, 16 ms
+ * <pre>
+ * D/TAG ( 3459): methodA: begin
+ * D/TAG ( 3459): methodA: 9 ms, work A
+ * D/TAG ( 3459): methodA: 1 ms, work B
+ * D/TAG ( 3459): methodA: 6 ms, work C
+ * D/TAG ( 3459): methodA: end, 16 ms
+ * </pre>
*/
public class TimingLogger {
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 1328525..74318ba 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1319,21 +1319,24 @@
* @param y New absolute Y location.
*/
public final void setLocation(float x, float y) {
- mXOffset = x - mDataSamples[mLastDataSampleIndex + SAMPLE_X];
- mYOffset = y - mDataSamples[mLastDataSampleIndex + SAMPLE_Y];
+ final float[] dataSamples = mDataSamples;
+ final int lastDataSampleIndex = mLastDataSampleIndex;
+ mXOffset = x - dataSamples[lastDataSampleIndex + SAMPLE_X];
+ mYOffset = y - dataSamples[lastDataSampleIndex + SAMPLE_Y];
}
private final void getPointerCoordsAtSampleIndex(int sampleIndex,
PointerCoords outPointerCoords) {
- outPointerCoords.x = mDataSamples[sampleIndex + SAMPLE_X] + mXOffset;
- outPointerCoords.y = mDataSamples[sampleIndex + SAMPLE_Y] + mYOffset;
- outPointerCoords.pressure = mDataSamples[sampleIndex + SAMPLE_PRESSURE];
- outPointerCoords.size = mDataSamples[sampleIndex + SAMPLE_SIZE];
- outPointerCoords.touchMajor = mDataSamples[sampleIndex + SAMPLE_TOUCH_MAJOR];
- outPointerCoords.touchMinor = mDataSamples[sampleIndex + SAMPLE_TOUCH_MINOR];
- outPointerCoords.toolMajor = mDataSamples[sampleIndex + SAMPLE_TOOL_MAJOR];
- outPointerCoords.toolMinor = mDataSamples[sampleIndex + SAMPLE_TOOL_MINOR];
- outPointerCoords.orientation = mDataSamples[sampleIndex + SAMPLE_ORIENTATION];
+ final float[] dataSamples = mDataSamples;
+ outPointerCoords.x = dataSamples[sampleIndex + SAMPLE_X] + mXOffset;
+ outPointerCoords.y = dataSamples[sampleIndex + SAMPLE_Y] + mYOffset;
+ outPointerCoords.pressure = dataSamples[sampleIndex + SAMPLE_PRESSURE];
+ outPointerCoords.size = dataSamples[sampleIndex + SAMPLE_SIZE];
+ outPointerCoords.touchMajor = dataSamples[sampleIndex + SAMPLE_TOUCH_MAJOR];
+ outPointerCoords.touchMinor = dataSamples[sampleIndex + SAMPLE_TOUCH_MINOR];
+ outPointerCoords.toolMajor = dataSamples[sampleIndex + SAMPLE_TOOL_MAJOR];
+ outPointerCoords.toolMinor = dataSamples[sampleIndex + SAMPLE_TOOL_MINOR];
+ outPointerCoords.orientation = dataSamples[sampleIndex + SAMPLE_ORIENTATION];
}
private final void setPointerCoordsAtSampleIndex(int sampleIndex,
@@ -1347,28 +1350,30 @@
private final void setPointerCoordsAtSampleIndex(int sampleIndex,
PointerCoords pointerCoords) {
- mDataSamples[sampleIndex + SAMPLE_X] = pointerCoords.x - mXOffset;
- mDataSamples[sampleIndex + SAMPLE_Y] = pointerCoords.y - mYOffset;
- mDataSamples[sampleIndex + SAMPLE_PRESSURE] = pointerCoords.pressure;
- mDataSamples[sampleIndex + SAMPLE_SIZE] = pointerCoords.size;
- mDataSamples[sampleIndex + SAMPLE_TOUCH_MAJOR] = pointerCoords.touchMajor;
- mDataSamples[sampleIndex + SAMPLE_TOUCH_MINOR] = pointerCoords.touchMinor;
- mDataSamples[sampleIndex + SAMPLE_TOOL_MAJOR] = pointerCoords.toolMajor;
- mDataSamples[sampleIndex + SAMPLE_TOOL_MINOR] = pointerCoords.toolMinor;
- mDataSamples[sampleIndex + SAMPLE_ORIENTATION] = pointerCoords.orientation;
+ final float[] dataSamples = mDataSamples;
+ dataSamples[sampleIndex + SAMPLE_X] = pointerCoords.x - mXOffset;
+ dataSamples[sampleIndex + SAMPLE_Y] = pointerCoords.y - mYOffset;
+ dataSamples[sampleIndex + SAMPLE_PRESSURE] = pointerCoords.pressure;
+ dataSamples[sampleIndex + SAMPLE_SIZE] = pointerCoords.size;
+ dataSamples[sampleIndex + SAMPLE_TOUCH_MAJOR] = pointerCoords.touchMajor;
+ dataSamples[sampleIndex + SAMPLE_TOUCH_MINOR] = pointerCoords.touchMinor;
+ dataSamples[sampleIndex + SAMPLE_TOOL_MAJOR] = pointerCoords.toolMajor;
+ dataSamples[sampleIndex + SAMPLE_TOOL_MINOR] = pointerCoords.toolMinor;
+ dataSamples[sampleIndex + SAMPLE_ORIENTATION] = pointerCoords.orientation;
}
private final void setPointerCoordsAtSampleIndex(int sampleIndex,
float x, float y, float pressure, float size) {
- mDataSamples[sampleIndex + SAMPLE_X] = x - mXOffset;
- mDataSamples[sampleIndex + SAMPLE_Y] = y - mYOffset;
- mDataSamples[sampleIndex + SAMPLE_PRESSURE] = pressure;
- mDataSamples[sampleIndex + SAMPLE_SIZE] = size;
- mDataSamples[sampleIndex + SAMPLE_TOUCH_MAJOR] = pressure;
- mDataSamples[sampleIndex + SAMPLE_TOUCH_MINOR] = pressure;
- mDataSamples[sampleIndex + SAMPLE_TOOL_MAJOR] = size;
- mDataSamples[sampleIndex + SAMPLE_TOOL_MINOR] = size;
- mDataSamples[sampleIndex + SAMPLE_ORIENTATION] = 0;
+ final float[] dataSamples = mDataSamples;
+ dataSamples[sampleIndex + SAMPLE_X] = x - mXOffset;
+ dataSamples[sampleIndex + SAMPLE_Y] = y - mYOffset;
+ dataSamples[sampleIndex + SAMPLE_PRESSURE] = pressure;
+ dataSamples[sampleIndex + SAMPLE_SIZE] = size;
+ dataSamples[sampleIndex + SAMPLE_TOUCH_MAJOR] = pressure;
+ dataSamples[sampleIndex + SAMPLE_TOUCH_MINOR] = pressure;
+ dataSamples[sampleIndex + SAMPLE_TOOL_MAJOR] = size;
+ dataSamples[sampleIndex + SAMPLE_TOOL_MINOR] = size;
+ dataSamples[sampleIndex + SAMPLE_ORIENTATION] = 0;
}
private final void incrementNumSamplesAndReserveStorage(int dataSampleStride) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c13bb8c..b565fc6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3438,7 +3438,7 @@
}
/**
- * Sets the pressed that for this view.
+ * Sets the pressed state for this view.
*
* @see #isClickable()
* @see #setClickable(boolean)
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index e2e3333..3678684 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -856,6 +856,9 @@
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if ((mGroupFlags & FLAG_SPLIT_MOTION_EVENTS) == FLAG_SPLIT_MOTION_EVENTS) {
+ if (mSplitMotionTargets == null) {
+ mSplitMotionTargets = new SplitMotionTargets();
+ }
return dispatchSplitTouchEvent(ev);
}
@@ -1036,19 +1039,21 @@
ev.setAction(action);
// We know we want to dispatch the event down, try to find a child
// who can handle it, start with the front-most child.
+ final long downTime = ev.getEventTime();
final View[] children = mChildren;
final int count = mChildrenCount;
for (int i = count - 1; i >= 0; i--) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
|| child.getAnimation() != null) {
- final MotionEvent childEvent = targets.filterMotionEventForChild(ev, child);
+ final MotionEvent childEvent =
+ targets.filterMotionEventForChild(ev, child, downTime);
if (childEvent != null) {
try {
final int childActionIndex = childEvent.findPointerIndex(actionId);
if (dispatchTouchEventIfInView(child, childEvent,
childActionIndex)) {
- targets.add(actionId, child);
+ targets.add(actionId, child, downTime);
return true;
}
@@ -1060,10 +1065,11 @@
}
// Didn't find a new target. Do we have a "primary" target to send to?
- final View primaryTarget = targets.getPrimaryTarget();
- if (primaryTarget != null) {
- final MotionEvent childEvent =
- targets.filterMotionEventForChild(ev, primaryTarget);
+ final SplitMotionTargets.TargetInfo primaryTargetInfo = targets.getPrimaryTarget();
+ if (primaryTargetInfo != null) {
+ final View primaryTarget = primaryTargetInfo.view;
+ final MotionEvent childEvent = targets.filterMotionEventForChild(ev,
+ primaryTarget, primaryTargetInfo.downTime);
if (childEvent != null) {
try {
// Calculate the offset point into the target's local coordinates
@@ -1081,7 +1087,7 @@
}
childEvent.setLocation(xc, yc);
if (primaryTarget.dispatchTouchEvent(childEvent)) {
- targets.add(actionId, primaryTarget);
+ targets.add(actionId, primaryTarget, primaryTargetInfo.downTime);
return true;
}
} finally {
@@ -1119,7 +1125,7 @@
mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
for (int uniqueIndex = 0; uniqueIndex < uniqueTargetCount; uniqueIndex++) {
- final View target = targets.getUniqueTargetAt(uniqueIndex);
+ final View target = targets.getUniqueTargetAt(uniqueIndex).view;
// Calculate the offset point into the target's local coordinates
float xc = scrolledXFloat - (float) target.mLeft;
@@ -1150,9 +1156,11 @@
boolean handled = false;
for (int uniqueIndex = 0; uniqueIndex < uniqueTargetCount; uniqueIndex++) {
- final View target = targets.getUniqueTargetAt(uniqueIndex);
+ final SplitMotionTargets.TargetInfo targetInfo = targets.getUniqueTargetAt(uniqueIndex);
+ final View target = targetInfo.view;
- final MotionEvent targetEvent = targets.filterMotionEventForChild(ev, target);
+ final MotionEvent targetEvent =
+ targets.filterMotionEventForChild(ev, target, targetInfo.downTime);
if (targetEvent == null) {
continue;
}
@@ -1187,7 +1195,13 @@
uniqueTargetCount--;
}
- handled |= target.dispatchTouchEvent(targetEvent);
+ final boolean childHandled = target.dispatchTouchEvent(targetEvent);
+ handled |= childHandled;
+ if (!childHandled) {
+ // Child doesn't want these events anymore, but we're still dispatching
+ // other split events to children.
+ targets.removeView(target);
+ }
} finally {
targetEvent.recycle();
}
@@ -1223,9 +1237,6 @@
// but perhaps this should handle that case and send ACTION_CANCELs to any child views
// with gestures in progress when this is changed.
if (split) {
- if ((mGroupFlags & FLAG_SPLIT_MOTION_EVENTS) == 0) {
- mSplitMotionTargets = new SplitMotionTargets();
- }
mGroupFlags |= FLAG_SPLIT_MOTION_EVENTS;
} else {
mGroupFlags &= ~FLAG_SPLIT_MOTION_EVENTS;
@@ -4103,9 +4114,8 @@
private static class SplitMotionTargets {
private SparseArray<View> mTargets;
- private View[] mUniqueTargets;
+ private TargetInfo[] mUniqueTargets;
private int mUniqueTargetCount;
- private long mDownTime;
private MotionEvent.PointerCoords[] mPointerCoords;
private int[] mPointerIds;
@@ -4114,7 +4124,7 @@
public SplitMotionTargets() {
mTargets = new SparseArray<View>();
- mUniqueTargets = new View[INITIAL_UNIQUE_MOTION_TARGETS_SIZE];
+ mUniqueTargets = new TargetInfo[INITIAL_UNIQUE_MOTION_TARGETS_SIZE];
mPointerIds = new int[INITIAL_BUCKET_SIZE];
mPointerCoords = new MotionEvent.PointerCoords[INITIAL_BUCKET_SIZE];
for (int i = 0; i < INITIAL_BUCKET_SIZE; i++) {
@@ -4124,31 +4134,32 @@
public void clear() {
mTargets.clear();
- Arrays.fill(mUniqueTargets, null);
+ final int count = mUniqueTargetCount;
+ for (int i = 0; i < count; i++) {
+ mUniqueTargets[i].recycle();
+ mUniqueTargets[i] = null;
+ }
mUniqueTargetCount = 0;
}
- public void add(int pointerId, View target) {
+ public void add(int pointerId, View target, long downTime) {
mTargets.put(pointerId, target);
final int uniqueCount = mUniqueTargetCount;
boolean addUnique = true;
for (int i = 0; i < uniqueCount; i++) {
- if (mUniqueTargets[i] == target) {
+ if (mUniqueTargets[i].view == target) {
addUnique = false;
}
}
if (addUnique) {
- if (mUniqueTargets == null) {
- mUniqueTargets = new View[INITIAL_UNIQUE_MOTION_TARGETS_SIZE];
- }
if (mUniqueTargets.length == uniqueCount) {
- View[] newTargets =
- new View[uniqueCount + INITIAL_UNIQUE_MOTION_TARGETS_SIZE];
+ TargetInfo[] newTargets =
+ new TargetInfo[uniqueCount + INITIAL_UNIQUE_MOTION_TARGETS_SIZE];
System.arraycopy(mUniqueTargets, 0, newTargets, 0, uniqueCount);
mUniqueTargets = newTargets;
}
- mUniqueTargets[uniqueCount] = target;
+ mUniqueTargets[uniqueCount] = TargetInfo.obtain(target, downTime);
mUniqueTargetCount++;
}
}
@@ -4161,7 +4172,7 @@
return mUniqueTargetCount;
}
- public View getUniqueTargetAt(int index) {
+ public TargetInfo getUniqueTargetAt(int index) {
return mUniqueTargets[index];
}
@@ -4185,18 +4196,29 @@
return mTargets.valueAt(index);
}
- public View getPrimaryTarget() {
+ public TargetInfo getPrimaryTarget() {
if (!isEmpty()) {
- return mUniqueTargets[0];
+ // Find the longest-lived target
+ long firstTime = Long.MAX_VALUE;
+ int firstIndex = 0;
+ final int uniqueCount = mUniqueTargetCount;
+ for (int i = 0; i < uniqueCount; i++) {
+ TargetInfo info = mUniqueTargets[i];
+ if (info.downTime < firstTime) {
+ firstTime = info.downTime;
+ firstIndex = i;
+ }
+ }
+ return mUniqueTargets[firstIndex];
}
return null;
}
public boolean hasTarget(View target) {
- final View[] unique = mUniqueTargets;
+ final TargetInfo[] unique = mUniqueTargets;
final int uniqueCount = mUniqueTargetCount;
for (int i = 0; i < uniqueCount; i++) {
- if (unique[i] == target) {
+ if (unique[i].view == target) {
return true;
}
}
@@ -4237,10 +4259,11 @@
}
private void removeUnique(View removeView) {
- View[] unique = mUniqueTargets;
+ TargetInfo[] unique = mUniqueTargets;
int uniqueCount = mUniqueTargetCount;
for (int i = 0; i < uniqueCount; i++) {
- if (unique[i] == removeView) {
+ if (unique[i].view == removeView) {
+ unique[i].recycle();
unique[i] = unique[--uniqueCount];
unique[uniqueCount] = null;
break;
@@ -4254,7 +4277,7 @@
* Return a new (obtain()ed) MotionEvent containing only data for pointers that should
* be dispatched to child. Don't forget to recycle it!
*/
- public MotionEvent filterMotionEventForChild(MotionEvent ev, View child) {
+ public MotionEvent filterMotionEventForChild(MotionEvent ev, View child, long downTime) {
int action = ev.getAction();
final int maskedAction = action & MotionEvent.ACTION_MASK;
@@ -4279,7 +4302,6 @@
if (maskedAction == MotionEvent.ACTION_DOWN) {
pointerCount++;
actionId = ev.getPointerId(0);
- mDownTime = ev.getDownTime();
} else if (maskedAction == MotionEvent.ACTION_POINTER_DOWN) {
pointerCount++;
@@ -4352,11 +4374,49 @@
(newActionIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
}
- MotionEvent result = MotionEvent.obtain(mDownTime, ev.getEventTime(),
+ MotionEvent result = MotionEvent.obtain(downTime, ev.getEventTime(),
action, pointerCount, mPointerIds, mPointerCoords, ev.getMetaState(),
ev.getXPrecision(), ev.getYPrecision(), ev.getDeviceId(), ev.getEdgeFlags(),
ev.getSource());
return result;
}
+
+ static class TargetInfo {
+ public View view;
+ public long downTime;
+
+ private TargetInfo mNextRecycled;
+
+ private static TargetInfo sRecycleBin;
+ private static int sRecycledCount;
+
+ private static int MAX_RECYCLED = 15;
+
+ private TargetInfo() {
+ }
+
+ public static TargetInfo obtain(View v, long time) {
+ TargetInfo info;
+ if (sRecycleBin == null) {
+ info = new TargetInfo();
+ } else {
+ info = sRecycleBin;
+ sRecycleBin = info.mNextRecycled;
+ sRecycledCount--;
+ }
+ info.view = v;
+ info.downTime = time;
+ return info;
+ }
+
+ public void recycle() {
+ if (sRecycledCount >= MAX_RECYCLED) {
+ return;
+ }
+ mNextRecycled = sRecycleBin;
+ sRecycleBin = this;
+ sRecycledCount++;
+ }
+ }
}
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 705af0f..6633367 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -771,6 +771,15 @@
return (mFeatures&flag) != 0;
}
+ /**
+ * @hide Used internally to help resolve conflicting features.
+ */
+ protected void removeFeature(int featureId) {
+ final int flag = 1<<featureId;
+ mFeatures &= ~flag;
+ mLocalFeatures &= ~(mContainer != null ? (flag&~mContainer.mFeatures) : flag);
+ }
+
public final void makeActive() {
if (mContainer != null) {
if (mContainer.mActiveChild != null) {
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index f3392d9..9a1e41c 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -307,7 +307,7 @@
* animated as well as the objects parents. (This is to support animation
* sizes being specifed relative to these dimensions.)
*
- * <p>Objects that interpret a Animations should call this method when
+ * <p>Objects that interpret Animations should call this method when
* the sizes of the object being animated and its parent are known, and
* before calling {@link #getTransformation}.
*
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index b021ded..e972c24 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -38,6 +38,8 @@
import junit.framework.Assert;
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.URLEncoder;
@@ -658,6 +660,96 @@
}
/**
+ * Called by JNI.
+ * Read from an InputStream into a supplied byte[]
+ * This method catches any exceptions so they don't crash the JVM.
+ * @param inputStream InputStream to read from.
+ * @param output Bytearray that gets the output.
+ * @return the number of bytes read, or -i if then end of stream has been reached
+ */
+ private static int readFromStream(InputStream inputStream, byte[] output) {
+ try {
+ return inputStream.read(output);
+ } catch(java.io.IOException e) {
+ // If we get an exception, return end of stream
+ return -1;
+ }
+ }
+
+ /**
+ * Get the InputStream for an Android resource
+ * There are three different kinds of android resources:
+ * - file:///android_res
+ * - file:///android_asset
+ * - content://
+ * @param url The url to load.
+ * @return An InputStream to the android resource
+ */
+ private InputStream inputStreamForAndroidResource(String url, int type) {
+ final int RESOURCE = 1;
+ final int ASSET = 2;
+ final int CONTENT = 3;
+
+ if (type == RESOURCE) {
+ // file:///android_res
+ if (url == null || url.length() == 0) {
+ Log.e(LOGTAG, "url has length 0 " + url);
+ return null;
+ }
+ int slash = url.indexOf('/');
+ int dot = url.indexOf('.', slash);
+ if (slash == -1 || dot == -1) {
+ Log.e(LOGTAG, "Incorrect res path: " + url);
+ return null;
+ }
+ String subClassName = url.substring(0, slash);
+ String fieldName = url.substring(slash + 1, dot);
+ String errorMsg = null;
+ try {
+ final Class<?> d = mContext.getApplicationContext()
+ .getClassLoader().loadClass(
+ mContext.getPackageName() + ".R$"
+ + subClassName);
+ final java.lang.reflect.Field field = d.getField(fieldName);
+ final int id = field.getInt(null);
+ TypedValue value = new TypedValue();
+ mContext.getResources().getValue(id, value, true);
+ if (value.type == TypedValue.TYPE_STRING) {
+ return mContext.getAssets().openNonAsset(
+ value.assetCookie, value.string.toString(),
+ AssetManager.ACCESS_STREAMING);
+ } else {
+ // Old stack only supports TYPE_STRING for res files
+ Log.e(LOGTAG, "not of type string: " + url);
+ return null;
+ }
+ } catch (Exception e) {
+ Log.e(LOGTAG, "Exception: " + url);
+ return null;
+ }
+
+ } else if (type == ASSET) {
+ // file:///android_asset
+ try {
+ AssetManager assets = mContext.getAssets();
+ return assets.open(url, AssetManager.ACCESS_STREAMING);
+ } catch (IOException e) {
+ return null;
+ }
+ } else if (type == CONTENT) {
+ try {
+ Uri uri = Uri.parse(url);
+ return mContext.getContentResolver().openInputStream(uri);
+ } catch (Exception e) {
+ Log.e(LOGTAG, "Exception: " + url);
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
* Start loading a resource.
* @param loaderHandle The native ResourceLoader that is the target of the
* data.
diff --git a/core/java/android/webkit/DeviceOrientationService.java b/core/java/android/webkit/DeviceOrientationService.java
index 07d3d2f..4ff849e 100755
--- a/core/java/android/webkit/DeviceOrientationService.java
+++ b/core/java/android/webkit/DeviceOrientationService.java
@@ -16,19 +16,39 @@
package android.webkit;
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.os.Handler;
import android.webkit.DeviceOrientationManager;
import java.lang.Runnable;
+import java.util.List;
-final class DeviceOrientationService {
+final class DeviceOrientationService implements SensorEventListener {
+ // The gravity vector expressed in the body frame.
+ private float[] mGravityVector;
+ // The geomagnetic vector expressed in the body frame.
+ private float[] mMagneticFieldVector;
+
private DeviceOrientationManager mManager;
private boolean mIsRunning;
private Handler mHandler;
+ private SensorManager mSensorManager;
+ private Context mContext;
+ private Double mAlpha;
+ private Double mBeta;
+ private Double mGamma;
- public DeviceOrientationService(DeviceOrientationManager manager) {
+ private static final double DELTA_DEGRESS = 1.0;
+
+ public DeviceOrientationService(DeviceOrientationManager manager, Context context) {
mManager = manager;
assert(mManager != null);
+ mContext = context;
+ assert(mContext != null);
}
public void start() {
@@ -55,9 +75,6 @@
private void sendErrorEvent() {
assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
- if (mHandler == null) {
- mHandler = new Handler();
- }
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -70,12 +87,128 @@
}
private void registerForSensors() {
- // Send the error event for now.
- // FIXME: Implement.
- sendErrorEvent();
+ if (mHandler == null) {
+ mHandler = new Handler();
+ }
+ if (!registerForAccelerometerSensor() || !registerForMagneticFieldSensor()) {
+ unregisterFromSensors();
+ sendErrorEvent();
+ }
+ }
+
+ private void getOrientationUsingGetRotationMatrix() {
+ if (mGravityVector == null || mMagneticFieldVector == null) {
+ return;
+ }
+
+ // Get the rotation matrix.
+ // The rotation matrix that transforms from the body frame to the earth frame.
+ float[] deviceRotationMatrix = new float[9];
+ if (!SensorManager.getRotationMatrix(
+ deviceRotationMatrix, null, mGravityVector, mMagneticFieldVector)) {
+ return;
+ }
+
+ // Convert rotation matrix to rotation angles.
+ // Assuming that the rotations are appied in the order listed at
+ // http://developer.android.com/reference/android/hardware/SensorEvent.html#values
+ // the rotations are applied about the same axes and in the same order as required by the
+ // API. The only conversions are sign changes as follows.
+ // The angles are in radians
+ float[] rotationAngles = new float[3];
+ SensorManager.getOrientation(deviceRotationMatrix, rotationAngles);
+ double alpha = Math.toDegrees(-rotationAngles[0]) - 90.0;
+ while (alpha < 0.0) { alpha += 360.0; } // [0, 360)
+ double beta = Math.toDegrees(-rotationAngles[1]);
+ while (beta < -180.0) { beta += 360.0; } // [-180, 180)
+ double gamma = Math.toDegrees(rotationAngles[2]);
+ while (gamma < -90.0) { gamma += 360.0; } // [-90, 90)
+
+ maybeSendChange(alpha, beta, gamma);
+ }
+
+ private SensorManager getSensorManager() {
+ assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
+ if (mSensorManager == null) {
+ mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+ }
+ return mSensorManager;
+ }
+
+ private boolean registerForAccelerometerSensor() {
+ List<Sensor> sensors = getSensorManager().getSensorList(Sensor.TYPE_ACCELEROMETER);
+ if (sensors.isEmpty()) {
+ return false;
+ }
+ // TODO: Consider handling multiple sensors.
+ return getSensorManager().registerListener(
+ this, sensors.get(0), SensorManager.SENSOR_DELAY_FASTEST, mHandler);
+ }
+
+ private boolean registerForMagneticFieldSensor() {
+ List<Sensor> sensors = getSensorManager().getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
+ if (sensors.isEmpty()) {
+ return false;
+ }
+ // TODO: Consider handling multiple sensors.
+ return getSensorManager().registerListener(
+ this, sensors.get(0), SensorManager.SENSOR_DELAY_FASTEST, mHandler);
}
private void unregisterFromSensors() {
- // FIXME: Implement.
+ getSensorManager().unregisterListener(this);
+ }
+
+ private void maybeSendChange(double alpha, double beta, double gamma) {
+ assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
+ if (mAlpha == null || mBeta == null || mGamma == null
+ || Math.abs(alpha - mAlpha) > DELTA_DEGRESS
+ || Math.abs(beta - mBeta) > DELTA_DEGRESS
+ || Math.abs(gamma - mGamma) > DELTA_DEGRESS) {
+ mAlpha = alpha;
+ mBeta = beta;
+ mGamma = gamma;
+ mManager.onOrientationChange(mAlpha, mBeta, mGamma);
+ }
+ }
+
+ /**
+ * SensorEventListener implementation.
+ * Callbacks happen on the thread on which we registered - the WebCore thread.
+ */
+ public void onSensorChanged(SensorEvent event) {
+ assert(event.values.length == 3);
+ assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
+
+ if (!mIsRunning) {
+ return;
+ }
+
+ switch (event.sensor.getType()) {
+ case Sensor.TYPE_ACCELEROMETER:
+ if (mGravityVector == null) {
+ mGravityVector = new float[3];
+ }
+ mGravityVector[0] = event.values[0];
+ mGravityVector[1] = event.values[1];
+ mGravityVector[2] = event.values[2];
+ getOrientationUsingGetRotationMatrix();
+ break;
+ case Sensor.TYPE_MAGNETIC_FIELD:
+ if (mMagneticFieldVector == null) {
+ mMagneticFieldVector = new float[3];
+ }
+ mMagneticFieldVector[0] = event.values[0];
+ mMagneticFieldVector[1] = event.values[1];
+ mMagneticFieldVector[2] = event.values[2];
+ getOrientationUsingGetRotationMatrix();
+ break;
+ default:
+ assert(false);
+ }
+ }
+
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
}
}
diff --git a/core/java/android/webkit/PluginManager.java b/core/java/android/webkit/PluginManager.java
index cdcb662..f7d1134 100644
--- a/core/java/android/webkit/PluginManager.java
+++ b/core/java/android/webkit/PluginManager.java
@@ -149,41 +149,11 @@
continue;
}
- // check if the plugin has the required permissions
- String permissions[] = pkgInfo.requestedPermissions;
- if (permissions == null) {
+ // check if the plugin has the required permissions and
+ // signatures
+ if (!containsPluginPermissionAndSignatures(pkgInfo)) {
continue;
}
- boolean permissionOk = false;
- for (String permit : permissions) {
- if (PLUGIN_PERMISSION.equals(permit)) {
- permissionOk = true;
- break;
- }
- }
- if (!permissionOk) {
- continue;
- }
-
- // check to ensure the plugin is properly signed
- Signature signatures[] = pkgInfo.signatures;
- if (signatures == null) {
- continue;
- }
- if (SystemProperties.getBoolean("ro.secure", false)) {
- boolean signatureMatch = false;
- for (Signature signature : signatures) {
- for (int i = 0; i < SIGNATURES.length; i++) {
- if (SIGNATURES[i].equals(signature)) {
- signatureMatch = true;
- break;
- }
- }
- }
- if (!signatureMatch) {
- continue;
- }
- }
// determine the type of plugin from the manifest
if (serviceInfo.metaData == null) {
@@ -226,6 +196,64 @@
}
/* package */
+ boolean containsPluginPermissionAndSignatures(String pluginAPKName) {
+ PackageManager pm = mContext.getPackageManager();
+
+ // retrieve information from the plugin's manifest
+ try {
+ PackageInfo pkgInfo = pm.getPackageInfo(pluginAPKName, PackageManager.GET_PERMISSIONS
+ | PackageManager.GET_SIGNATURES);
+ if (pkgInfo != null) {
+ return containsPluginPermissionAndSignatures(pkgInfo);
+ }
+ } catch (NameNotFoundException e) {
+ Log.w(LOGTAG, "Can't find plugin: " + pluginAPKName);
+ }
+ return false;
+ }
+
+ private static boolean containsPluginPermissionAndSignatures(PackageInfo pkgInfo) {
+
+ // check if the plugin has the required permissions
+ String permissions[] = pkgInfo.requestedPermissions;
+ if (permissions == null) {
+ return false;
+ }
+ boolean permissionOk = false;
+ for (String permit : permissions) {
+ if (PLUGIN_PERMISSION.equals(permit)) {
+ permissionOk = true;
+ break;
+ }
+ }
+ if (!permissionOk) {
+ return false;
+ }
+
+ // check to ensure the plugin is properly signed
+ Signature signatures[] = pkgInfo.signatures;
+ if (signatures == null) {
+ return false;
+ }
+ if (SystemProperties.getBoolean("ro.secure", false)) {
+ boolean signatureMatch = false;
+ for (Signature signature : signatures) {
+ for (int i = 0; i < SIGNATURES.length; i++) {
+ if (SIGNATURES[i].equals(signature)) {
+ signatureMatch = true;
+ break;
+ }
+ }
+ }
+ if (!signatureMatch) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /* package */
String getPluginsAPKName(String pluginLib) {
// basic error checking on input params
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 4823407..5d9ab90 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -18,10 +18,14 @@
import android.annotation.Widget;
import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.IntentFilter;
import android.content.DialogInterface.OnCancelListener;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.Intent;
import android.database.DataSetObserver;
import android.graphics.Bitmap;
@@ -40,6 +44,7 @@
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.net.http.SslCertificate;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -92,6 +97,7 @@
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -877,6 +883,7 @@
* such as the mZoomManager.
*/
init();
+ setupPackageListener(context);
updateMultiTouchSupport(context);
if (privateBrowsing) {
@@ -884,6 +891,96 @@
}
}
+ /*
+ * The intent receiver that monitors for changes to relevant packages (e.g.,
+ * sGoogleApps) and notifies WebViewCore of their existence.
+ */
+ private static BroadcastReceiver sPackageInstallationReceiver = null;
+
+ /*
+ * A set of Google packages we monitor for the
+ * navigator.isApplicationInstalled() API. Add additional packages as
+ * needed.
+ */
+ private static Set<String> sGoogleApps;
+ static {
+ sGoogleApps = new HashSet<String>();
+ sGoogleApps.add("com.google.android.youtube");
+ }
+
+ private void setupPackageListener(Context context) {
+
+ /*
+ * we must synchronize the instance check and the creation of the
+ * receiver to ensure that only ONE receiver exists for all WebView
+ * instances.
+ */
+ synchronized (WebView.class) {
+
+ // if the receiver already exists then we do not need to register it
+ // again
+ if (sPackageInstallationReceiver != null) {
+ return;
+ }
+
+ IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addDataScheme("package");
+ sPackageInstallationReceiver = new BroadcastReceiver() {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ final String packageName = intent.getData().getSchemeSpecificPart();
+ final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+ if (Intent.ACTION_PACKAGE_REMOVED.equals(action) && replacing) {
+ // if it is replacing, refreshPlugins() when adding
+ return;
+ }
+
+ if (sGoogleApps.contains(packageName)) {
+ if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+ mWebViewCore.sendMessage(EventHub.ADD_PACKAGE_NAME, packageName);
+ } else {
+ mWebViewCore.sendMessage(EventHub.REMOVE_PACKAGE_NAME, packageName);
+ }
+ }
+
+ PluginManager pm = PluginManager.getInstance(context);
+ if (pm.containsPluginPermissionAndSignatures(packageName)) {
+ pm.refreshPlugins(Intent.ACTION_PACKAGE_ADDED.equals(action));
+ }
+ }
+ };
+
+ context.getApplicationContext().registerReceiver(sPackageInstallationReceiver, filter);
+ }
+
+ // check if any of the monitored apps are already installed
+ AsyncTask<Void, Void, Set<String>> task = new AsyncTask<Void, Void, Set<String>>() {
+
+ @Override
+ protected Set<String> doInBackground(Void... unused) {
+ Set<String> installedPackages = new HashSet<String>();
+ PackageManager pm = mContext.getPackageManager();
+ List<PackageInfo> packages = pm.getInstalledPackages(0);
+ for (PackageInfo p : packages) {
+ if (sGoogleApps.contains(p.packageName)) {
+ installedPackages.add(p.packageName);
+ }
+ }
+ return installedPackages;
+ }
+
+ // Executes on the UI thread
+ @Override
+ protected void onPostExecute(Set<String> installedPackages) {
+ mWebViewCore.sendMessage(EventHub.ADD_PACKAGE_NAMES, installedPackages);
+ }
+ };
+ task.execute();
+ }
+
void updateMultiTouchSupport(Context context) {
mZoomManager.updateMultiTouchSupport(context);
}
@@ -3076,45 +3173,6 @@
return (mWebViewCore != null) ? mWebViewCore.getSettings() : null;
}
- /**
- * Use this method to inform the webview about packages that are installed
- * in the system. This information will be used by the
- * navigator.isApplicationInstalled() API.
- * @param packageNames is a set of package names that are known to be
- * installed in the system.
- *
- * @hide not a public API
- */
- public void addPackageNames(Set<String> packageNames) {
- mWebViewCore.sendMessage(EventHub.ADD_PACKAGE_NAMES, packageNames);
- }
-
- /**
- * Use this method to inform the webview about single packages that are
- * installed in the system. This information will be used by the
- * navigator.isApplicationInstalled() API.
- * @param packageName is the name of a package that is known to be
- * installed in the system.
- *
- * @hide not a public API
- */
- public void addPackageName(String packageName) {
- mWebViewCore.sendMessage(EventHub.ADD_PACKAGE_NAME, packageName);
- }
-
- /**
- * Use this method to inform the webview about packages that are uninstalled
- * in the system. This information will be used by the
- * navigator.isApplicationInstalled() API.
- * @param packageName is the name of a package that has been uninstalled in
- * the system.
- *
- * @hide not a public API
- */
- public void removePackageName(String packageName) {
- mWebViewCore.sendMessage(EventHub.REMOVE_PACKAGE_NAME, packageName);
- }
-
/**
* Return the list of currently loaded plugins.
* @return The list of currently loaded plugins.
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 860edf2..fad4323 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -441,6 +441,8 @@
*/
private native void nativeClearContent();
+ private native void nativeContentInvalidateAll();
+
/**
* Redraw a portion of the picture set. The Point wh returns the
* width and height of the overall picture.
@@ -1880,10 +1882,10 @@
synchronized (core) {
core.mDrawIsPaused = false;
- if (core.mDrawIsScheduled) {
- core.mDrawIsScheduled = false;
- core.contentDraw();
- }
+ // always redraw on resume to reenable gif animations
+ core.mDrawIsScheduled = false;
+ core.nativeContentInvalidateAll();
+ core.contentDraw();
}
}
}
@@ -2504,7 +2506,8 @@
protected DeviceOrientationService getDeviceOrientationService() {
if (mDeviceOrientationService == null) {
- mDeviceOrientationService = new DeviceOrientationService(mDeviceOrientationManager);
+ mDeviceOrientationService =
+ new DeviceOrientationService(mDeviceOrientationManager, mContext);
}
return mDeviceOrientationService;
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 0f52fc8..3a4487c 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -21,8 +21,9 @@
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
-import android.graphics.Shader;
import android.graphics.Rect;
+import android.graphics.Shader;
+import android.graphics.drawable.Animatable;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ClipDrawable;
@@ -30,11 +31,14 @@
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.StateListDrawable;
-import android.graphics.drawable.Animatable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.graphics.drawable.shapes.Shape;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.Gravity;
+import android.view.RemotableViewMethod;
import android.view.View;
import android.view.ViewDebug;
import android.view.animation.AlphaAnimation;
@@ -44,9 +48,6 @@
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;
import android.widget.RemoteViews.RemoteView;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.SystemClock;
import com.android.internal.R;
@@ -763,6 +764,7 @@
}
@Override
+ @RemotableViewMethod
public void setVisibility(int v) {
if (getVisibility() != v) {
super.setVisibility(v);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 25c5b24..ec54e9df 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6532,6 +6532,13 @@
if (!mFrozenWithFocus || (selStart < 0 || selEnd < 0)) {
boolean selMoved = mSelectionMoved;
+ if (mSelectionModifierCursorController != null) {
+ final int touchOffset =
+ ((SelectionModifierCursorController) mSelectionModifierCursorController).
+ getMinTouchOffset();
+ Selection.setSelection((Spannable) mText, touchOffset);
+ }
+
if (mMovement != null) {
mMovement.onTakeFocus(this, (Spannable) mText, direction);
}
@@ -6744,13 +6751,14 @@
if (isTextEditable()) {
if (action == MotionEvent.ACTION_UP && isFocused() && !mScrolled) {
InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
final int newSelStart = getSelectionStart();
final int newSelEnd = getSelectionEnd();
CommitSelectionReceiver csr = null;
- if (newSelStart != oldSelStart || newSelEnd != oldSelEnd) {
+ if (newSelStart != oldSelStart || newSelEnd != oldSelEnd ||
+ didTouchFocusSelect()) {
csr = new CommitSelectionReceiver(oldSelStart, oldSelEnd,
newSelStart, newSelEnd);
}
@@ -7271,17 +7279,16 @@
* this will be {@link android.R.id#copyUrl} or {@link android.R.id#selectTextMode}.
*/
public boolean onTextContextMenuItem(int id) {
- int selStart = getSelectionStart();
- int selEnd = getSelectionEnd();
-
- if (!isFocused()) {
- selStart = 0;
- selEnd = mText.length();
+ int min = 0;
+ int max = mText.length();
+
+ if (isFocused()) {
+ int selStart = getSelectionStart();
+ int selEnd = getSelectionEnd();
+ min = Math.max(0, Math.min(selStart, selEnd));
+ max = Math.max(0, Math.max(selStart, selEnd));
}
- int min = Math.max(0, Math.min(selStart, selEnd));
- int max = Math.max(0, Math.max(selStart, selEnd));
-
ClipboardManager clipboard = (ClipboardManager)getContext()
.getSystemService(Context.CLIPBOARD_SERVICE);
@@ -7600,7 +7607,7 @@
/**
* Update the controller's position.
*/
- public void updatePosition(int offset);
+ public void updatePosition(int x, int y);
/**
* The controller and the cursor's positions can be link by a fixed offset,
@@ -7635,8 +7642,8 @@
// Vertical extension of the touch region
int mTopExtension, mBottomExtension;
// Position of the virtual finger position on screen
- int mHopSpotVertcalPosition;
-
+ int mHotSpotVerticalPosition;
+
Handle(Drawable drawable) {
mDrawable = drawable;
}
@@ -7648,8 +7655,7 @@
final int lineTop = mLayout.getLineTop(line);
final int lineBottom = mLayout.getLineBottom(line);
- mHopSpotVertcalPosition = lineTop + (bottom ? (3 * (lineBottom - lineTop)) / 4 :
- (lineBottom - lineTop) / 4);
+ mHotSpotVerticalPosition = lineTop;
final Rect bounds = sCursorControllerTempRect;
bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - drawableWidth / 2.0);
@@ -7669,7 +7675,7 @@
int boundTopBefore = bounds.top;
convertFromViewportToContentCoordinates(bounds);
- mHopSpotVertcalPosition += bounds.top - boundTopBefore;
+ mHotSpotVerticalPosition += bounds.top - boundTopBefore;
mDrawable.setBounds(bounds);
postInvalidate();
}
@@ -7720,7 +7726,7 @@
public void show() {
updateDrawablePosition();
- // Has to be done after updatePosition, so that previous position invalidate
+ // Has to be done after updateDrawablePosition, so that previous position invalidate
// in only done if necessary.
mIsVisible = true;
}
@@ -7757,12 +7763,14 @@
}
}
- public void updatePosition(int offset) {
- if (offset == getSelectionStart()) {
- return; // No change, no need to redraw
+ public void updatePosition(int x, int y) {
+ final int previousOffset = getSelectionStart();
+ int offset = getHysteresisOffset(x, y, previousOffset);
+
+ if (offset != previousOffset) {
+ Selection.setSelection((Spannable) mText, offset);
+ updateDrawablePosition();
}
- Selection.setSelection((Spannable) mText, offset);
- updateDrawablePosition();
}
private void updateDrawablePosition() {
@@ -7808,7 +7816,7 @@
final Rect bounds = mHandle.mDrawable.getBounds();
mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
- mOffsetY = mHandle.mHopSpotVertcalPosition - y;
+ mOffsetY = mHandle.mHotSpotVerticalPosition - y;
mOnDownTimerStart = event.getEventTime();
}
@@ -7863,7 +7871,7 @@
public void show() {
updateDrawablesPositions();
- // Has to be done after updatePosition, so that previous position invalidate
+ // Has to be done after updateDrawablePositions, so that previous position invalidate
// in only done if necessary.
mIsVisible = true;
mFadeOutTimerStart = -1;
@@ -7905,10 +7913,13 @@
}
}
- public void updatePosition(int offset) {
+ public void updatePosition(int x, int y) {
int selectionStart = getSelectionStart();
int selectionEnd = getSelectionEnd();
+ final int previousOffset = mStartIsDragged ? selectionStart : selectionEnd;
+ int offset = getHysteresisOffset(x, y, previousOffset);
+
// Handle the case where start and end are swapped, making sure start <= end
if (mStartIsDragged) {
if (offset <= selectionEnd) {
@@ -7955,7 +7966,8 @@
return;
}
- boolean oneLineSelection = mLayout.getLineForOffset(selectionStart) == mLayout.getLineForOffset(selectionEnd);
+ boolean oneLineSelection =
+ mLayout.getLineForOffset(selectionStart) == mLayout.getLineForOffset(selectionEnd);
mStartHandle.positionAtCursor(selectionStart, oneLineSelection);
mEndHandle.positionAtCursor(selectionEnd, true);
@@ -7990,7 +8002,7 @@
final Handle draggedHandle = mStartIsDragged ? mStartHandle : mEndHandle;
final Rect bounds = draggedHandle.mDrawable.getBounds();
mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
- mOffsetY = draggedHandle.mHopSpotVertcalPosition - y;
+ mOffsetY = draggedHandle.mHotSpotVerticalPosition - y;
((ArrowKeyMovementMethod)mMovement).setCursorController(this);
}
@@ -8060,6 +8072,15 @@
stopSelectionActionMode();
}
+ private int getOffsetForHorizontal(int line, int x) {
+ x -= getTotalPaddingLeft();
+ // Clamp the position to inside of the view.
+ x = Math.max(0, x);
+ x = Math.min(getWidth() - getTotalPaddingRight() - 1, x);
+ x += getScrollX();
+ return getLayout().getOffsetForHorizontal(line, x);
+ }
+
/**
* Get the offset character closest to the specified absolute position.
*
@@ -8071,32 +8092,44 @@
* @hide
*/
public int getOffset(int x, int y) {
- x -= getTotalPaddingLeft();
+ if (getLayout() == null) return -1;
+
y -= getTotalPaddingTop();
-
// Clamp the position to inside of the view.
- if (x < 0) {
- x = 0;
- } else if (x >= (getWidth() - getTotalPaddingRight())) {
- x = getWidth()-getTotalPaddingRight() - 1;
- }
- if (y < 0) {
- y = 0;
- } else if (y >= (getHeight() - getTotalPaddingBottom())) {
- y = getHeight()-getTotalPaddingBottom() - 1;
- }
-
- x += getScrollX();
+ y = Math.max(0, y);
+ y = Math.min(getHeight() - getTotalPaddingBottom() - 1, y);
y += getScrollY();
- Layout layout = getLayout();
- if (layout != null) {
- final int line = layout.getLineForVertical(y);
- final int offset = layout.getOffsetForHorizontal(line, x);
- return offset;
- } else {
- return -1;
+ final int line = getLayout().getLineForVertical(y);
+ final int offset = getOffsetForHorizontal(line, x);
+ return offset;
+ }
+
+ int getHysteresisOffset(int x, int y, int previousOffset) {
+ final Layout layout = getLayout();
+ if (layout == null) return -1;
+
+ y -= getTotalPaddingTop();
+ // Clamp the position to inside of the view.
+ y = Math.max(0, y);
+ y = Math.min(getHeight() - getTotalPaddingBottom() - 1, y);
+ y += getScrollY();
+
+ int line = getLayout().getLineForVertical(y);
+
+ final int previousLine = layout.getLineForOffset(previousOffset);
+ final int previousLineTop = layout.getLineTop(previousLine);
+ final int previousLineBottom = layout.getLineBottom(previousLine);
+ final int hysteresisThreshold = (previousLineBottom - previousLineTop) / 2;
+
+ // If new line is just before or after previous line and y position is less than
+ // hysteresisThreshold away from previous line, keep cursor on previous line.
+ if (((line == previousLine + 1) && ((y - previousLineBottom) < hysteresisThreshold)) ||
+ ((line == previousLine - 1) && ((previousLineTop - y) < hysteresisThreshold))) {
+ line = previousLine;
}
+
+ return getOffsetForHorizontal(line, x);
}
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java
index d1aff2a..e07c54f 100644
--- a/core/java/com/android/internal/app/ShutdownThread.java
+++ b/core/java/com/android/internal/app/ShutdownThread.java
@@ -134,7 +134,7 @@
private static void beginShutdownSequence(Context context) {
synchronized (sIsStartedGuard) {
if (sIsStarted) {
- Log.d(TAG, "Request to shutdown already running, returning.");
+ Log.d(TAG, "Shutdown sequence already running, returning.");
return;
}
sIsStarted = true;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index a70dbf6..0a1c8ff 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3693,8 +3693,8 @@
mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart;
mDischargeCurrentLevel = level;
if (level < mDischargeUnplugLevel) {
- mLowDischargeAmountSinceCharge = mDischargeUnplugLevel-level-1;
- mHighDischargeAmountSinceCharge = mDischargeUnplugLevel-level;
+ mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
+ mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
}
doPlugLocked(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime));
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 0b62a67..90423be 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -19,6 +19,7 @@
import android.app.admin.DevicePolicyManager;
import android.content.ContentResolver;
import android.content.Context;
+import android.os.FileObserver;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -33,6 +34,7 @@
import com.android.internal.telephony.ITelephony;
import com.google.android.collect.Lists;
+import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
@@ -40,6 +42,7 @@
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Utilities for the lock patten and its settings.
@@ -48,8 +51,9 @@
private static final String TAG = "LockPatternUtils";
- private static final String LOCK_PATTERN_FILE = "/system/gesture.key";
- private static final String LOCK_PASSWORD_FILE = "/system/password.key";
+ private static final String SYSTEM_DIRECTORY = "/system/";
+ private static final String LOCK_PATTERN_FILE = "gesture.key";
+ private static final String LOCK_PASSWORD_FILE = "password.key";
/**
* The maximum number of incorrect attempts before the user is prevented
@@ -100,6 +104,10 @@
private static String sLockPatternFilename;
private static String sLockPasswordFilename;
+ private static final AtomicBoolean sHaveNonZeroPatternFile = new AtomicBoolean(false);
+ private static final AtomicBoolean sHaveNonZeroPasswordFile = new AtomicBoolean(false);
+ private static FileObserver sPasswordObserver;
+
public DevicePolicyManager getDevicePolicyManager() {
if (mDevicePolicyManager == null) {
mDevicePolicyManager =
@@ -117,14 +125,31 @@
public LockPatternUtils(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
- // Initialize the location of gesture lock file
- if (sLockPatternFilename == null) {
- sLockPatternFilename = android.os.Environment.getDataDirectory()
- .getAbsolutePath() + LOCK_PATTERN_FILE;
- sLockPasswordFilename = android.os.Environment.getDataDirectory()
- .getAbsolutePath() + LOCK_PASSWORD_FILE;
- }
+ // Initialize the location of gesture & PIN lock files
+ if (sLockPatternFilename == null) {
+ String dataSystemDirectory =
+ android.os.Environment.getDataDirectory().getAbsolutePath() +
+ SYSTEM_DIRECTORY;
+ sLockPatternFilename = dataSystemDirectory + LOCK_PATTERN_FILE;
+ sLockPasswordFilename = dataSystemDirectory + LOCK_PASSWORD_FILE;
+ sHaveNonZeroPatternFile.set(new File(sLockPatternFilename).length() > 0);
+ sHaveNonZeroPasswordFile.set(new File(sLockPasswordFilename).length() > 0);
+ int fileObserverMask = FileObserver.CLOSE_WRITE | FileObserver.DELETE |
+ FileObserver.MOVED_TO | FileObserver.CREATE;
+ sPasswordObserver = new FileObserver(dataSystemDirectory, fileObserverMask) {
+ public void onEvent(int event, String path) {
+ if (LOCK_PATTERN_FILE.equals(path)) {
+ Log.d(TAG, "lock pattern file changed");
+ sHaveNonZeroPatternFile.set(new File(sLockPatternFilename).length() > 0);
+ } else if (LOCK_PASSWORD_FILE.equals(path)) {
+ Log.d(TAG, "lock password file changed");
+ sHaveNonZeroPasswordFile.set(new File(sLockPasswordFilename).length() > 0);
+ }
+ }
+ };
+ sPasswordObserver.startWatching();
+ }
}
public int getRequestedMinimumPasswordLength() {
@@ -258,32 +283,11 @@
}
/**
- * Checks to see if the given file exists and contains any data. Returns
- * true if it does, false otherwise.
- *
- * @param filename
- * @return true if file exists and is non-empty.
- */
- private boolean nonEmptyFileExists(String filename) {
- try {
- // Check if we can read a byte from the file
- RandomAccessFile raf = new RandomAccessFile(filename, "r");
- raf.readByte();
- raf.close();
- return true;
- } catch (FileNotFoundException fnfe) {
- return false;
- } catch (IOException ioe) {
- return false;
- }
- }
-
- /**
* Check to see if the user has stored a lock pattern.
* @return Whether a saved pattern exists.
*/
public boolean savedPatternExists() {
- return nonEmptyFileExists(sLockPatternFilename);
+ return sHaveNonZeroPatternFile.get();
}
/**
@@ -291,7 +295,7 @@
* @return Whether a saved pattern exists.
*/
public boolean savedPasswordExists() {
- return nonEmptyFileExists(sLockPasswordFilename);
+ return sHaveNonZeroPasswordFile.get();
}
/**
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 17f5daf..f78f83c 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -453,30 +453,23 @@
// return -1 if there was an error querying the buffer size.
static jint android_media_AudioRecord_get_min_buff_size(JNIEnv *env, jobject thiz,
jint sampleRateInHertz, jint nbChannels, jint audioFormat) {
-
- size_t inputBuffSize = 0;
+
LOGV(">> android_media_AudioRecord_get_min_buff_size(%d, %d, %d)", sampleRateInHertz, nbChannels, audioFormat);
-
- status_t result = AudioSystem::getInputBufferSize(
- sampleRateInHertz,
- (audioFormat == javaAudioRecordFields.PCM16 ?
- AudioSystem::PCM_16_BIT : AudioSystem::PCM_8_BIT),
- nbChannels, &inputBuffSize);
- switch(result) {
- case(NO_ERROR):
- if(inputBuffSize == 0) {
- LOGV("Recording parameters are not supported: %dHz, %d channel(s), (java) format %d",
- sampleRateInHertz, nbChannels, audioFormat);
- return 0;
- } else {
- // the minimum buffer size is twice the hardware input buffer size
- return 2*inputBuffSize;
- }
- break;
- case(PERMISSION_DENIED):
- default:
- return -1;
+
+ int frameCount = 0;
+ status_t result = AudioRecord::getMinFrameCount(&frameCount,
+ sampleRateInHertz,
+ (audioFormat == javaAudioRecordFields.PCM16 ?
+ AudioSystem::PCM_16_BIT : AudioSystem::PCM_8_BIT),
+ nbChannels);
+
+ if (result == BAD_VALUE) {
+ return 0;
}
+ if (result != NO_ERROR) {
+ return -1;
+ }
+ return frameCount * nbChannels * (audioFormat == javaAudioRecordFields.PCM16 ? 2 : 1);
}
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index c559670..9d215b7 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -782,29 +782,13 @@
// returns -1 if there was an error querying the hardware.
static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thiz,
jint sampleRateInHertz, jint nbChannels, jint audioFormat) {
- int afSamplingRate;
- int afFrameCount;
- uint32_t afLatency;
-
- if (AudioSystem::getOutputSamplingRate(&afSamplingRate) != NO_ERROR) {
+
+ int frameCount = 0;
+ if (AudioTrack::getMinFrameCount(&frameCount, AudioSystem::DEFAULT,
+ sampleRateInHertz) != NO_ERROR) {
return -1;
}
- if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) {
- return -1;
- }
-
- if (AudioSystem::getOutputLatency(&afLatency) != NO_ERROR) {
- return -1;
- }
-
- // Ensure that buffer depth covers at least audio hardware latency
- uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSamplingRate);
- if (minBufCount < 2) minBufCount = 2;
- uint32_t minFrameCount = (afFrameCount*sampleRateInHertz*minBufCount)/afSamplingRate;
- int minBuffSize = minFrameCount
- * (audioFormat == javaAudioTrackFields.PCM16 ? 2 : 1)
- * nbChannels;
- return minBuffSize;
+ return frameCount * nbChannels * (audioFormat == javaAudioTrackFields.PCM16 ? 2 : 1);
}
// ----------------------------------------------------------------------------
diff --git a/core/res/res/drawable-hdpi/btn_check_label_background_light.9.png b/core/res/res/drawable-hdpi/btn_check_label_background_light.9.png
deleted file mode 100644
index 97e6806..0000000
--- a/core/res/res/drawable-hdpi/btn_check_label_background_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off.png b/core/res/res/drawable-hdpi/btn_check_off.png
index 911e1aa..aad9ef7 100644
--- a/core/res/res/drawable-hdpi/btn_check_off.png
+++ b/core/res/res/drawable-hdpi/btn_check_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable.png b/core/res/res/drawable-hdpi/btn_check_off_disable.png
index d72e2b9..eaee9e0 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disable.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_focused.png b/core/res/res/drawable-hdpi/btn_check_off_disable_focused.png
index d72e2b9..6d2c293 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_dark.png
new file mode 100644
index 0000000..d72e2b9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_focused_light.png b/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_check_off_disable_focused_light.png
rename to core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_disable_holo_dark.png
new file mode 100644
index 0000000..d72e2b9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_light.png b/core/res/res/drawable-hdpi/btn_check_off_disable_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_check_off_disable_light.png
rename to core/res/res/drawable-hdpi/btn_check_off_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_holo_dark.png
new file mode 100644
index 0000000..911e1aa
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_light.png b/core/res/res/drawable-hdpi/btn_check_off_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_check_off_light.png
rename to core/res/res/drawable-hdpi/btn_check_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_pressed.png b/core/res/res/drawable-hdpi/btn_check_off_pressed.png
index 08f41812..1c442e9 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png
new file mode 100644
index 0000000..08f41812
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_pressed_light.png b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_check_off_pressed_light.png
rename to core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_selected.png b/core/res/res/drawable-hdpi/btn_check_off_selected.png
index 264f102..b852b2c 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_selected.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_selected_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_selected_holo_dark.png
new file mode 100644
index 0000000..264f102
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_off_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_selected_light.png b/core/res/res/drawable-hdpi/btn_check_off_selected_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_check_off_selected_light.png
rename to core/res/res/drawable-hdpi/btn_check_off_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on.png b/core/res/res/drawable-hdpi/btn_check_on.png
index 5541c67..cd5c181 100644
--- a/core/res/res/drawable-hdpi/btn_check_on.png
+++ b/core/res/res/drawable-hdpi/btn_check_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable.png b/core/res/res/drawable-hdpi/btn_check_on_disable.png
index 7805458..b4fc51a 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disable.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_focused.png b/core/res/res/drawable-hdpi/btn_check_on_disable_focused.png
index 7805458..bf34647 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png
new file mode 100644
index 0000000..7805458
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_light.png b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_check_on_disable_focused_light.png
rename to core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disable_holo_dark.png
new file mode 100644
index 0000000..7805458
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_light.png b/core/res/res/drawable-hdpi/btn_check_on_disable_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_check_on_disable_light.png
rename to core/res/res/drawable-hdpi/btn_check_on_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
new file mode 100644
index 0000000..5541c67
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_light.png b/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_check_on_light.png
rename to core/res/res/drawable-hdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed.png b/core/res/res/drawable-hdpi/btn_check_on_pressed.png
index 37e3953..fa5c7a2 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
new file mode 100644
index 0000000..37e3953
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_light.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_check_on_pressed_light.png
rename to core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_selected.png b/core/res/res/drawable-hdpi/btn_check_on_selected.png
index a0beac4..a6a21ad 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_selected.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_selected_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_selected_holo_dark.png
new file mode 100644
index 0000000..a0beac4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_on_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_selected_light.png b/core/res/res/drawable-hdpi/btn_check_on_selected_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_check_on_selected_light.png
rename to core/res/res/drawable-hdpi/btn_check_on_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_label_background_light.9.png b/core/res/res/drawable-hdpi/btn_radio_label_background_light.9.png
deleted file mode 100644
index 45c5c6a..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_label_background_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off.png b/core/res/res/drawable-hdpi/btn_radio_off.png
index 301c97d..c0b14aa 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_off_holo_dark.png
new file mode 100644
index 0000000..301c97d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_light.png b/core/res/res/drawable-hdpi/btn_radio_off_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_radio_off_light.png
rename to core/res/res/drawable-hdpi/btn_radio_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_pressed.png b/core/res/res/drawable-hdpi/btn_radio_off_pressed.png
index 5e6ef2b..3189581 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_dark.png
new file mode 100644
index 0000000..5e6ef2b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_pressed_light.png b/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_radio_off_pressed_light.png
rename to core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_selected.png b/core/res/res/drawable-hdpi/btn_radio_off_selected.png
index d11ae85..f337703 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_selected.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_dark.png
new file mode 100644
index 0000000..d11ae85
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_selected_light.png b/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_radio_off_selected_light.png
rename to core/res/res/drawable-hdpi/btn_radio_off_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on.png b/core/res/res/drawable-hdpi/btn_radio_on.png
index 5b0dbe8..c90d2eb 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_on_holo_dark.png
new file mode 100644
index 0000000..5b0dbe8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_light.png b/core/res/res/drawable-hdpi/btn_radio_on_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_radio_on_light.png
rename to core/res/res/drawable-hdpi/btn_radio_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_pressed.png b/core/res/res/drawable-hdpi/btn_radio_on_pressed.png
index c3a0d48..d79450b8 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_dark.png
new file mode 100644
index 0000000..c3a0d48
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_pressed_light.png b/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_radio_on_pressed_light.png
rename to core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_selected.png b/core/res/res/drawable-hdpi/btn_radio_on_selected.png
index 6c05f47..db50c43 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_selected.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_dark.png
new file mode 100644
index 0000000..6c05f47
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_selected_light.png b/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_light.png
similarity index 100%
rename from core/res/res/drawable-hdpi/btn_radio_on_selected_light.png
rename to core/res/res/drawable-hdpi/btn_radio_on_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png b/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png
index 99a67b9..41b776b 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_bright_opaque.9.png b/core/res/res/drawable-hdpi/divider_horizontal_bright_opaque.9.png
index cfe258b..eb75a22 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_bright_opaque.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png b/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png
index 338d840..55a5e53 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_dark_opaque.9.png b/core/res/res/drawable-hdpi/divider_horizontal_dark_opaque.9.png
index 9444f0d..60e2cb2 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_dark_opaque.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_dim_dark.9.png b/core/res/res/drawable-hdpi/divider_horizontal_dim_dark.9.png
index 63859f7..cf34613 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_dim_dark.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_dim_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_bright.9.png b/core/res/res/drawable-hdpi/divider_vertical_bright.9.png
index 99a67b9..41b776b 100644
--- a/core/res/res/drawable-hdpi/divider_vertical_bright.9.png
+++ b/core/res/res/drawable-hdpi/divider_vertical_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_bright_opaque.9.png b/core/res/res/drawable-hdpi/divider_vertical_bright_opaque.9.png
index 5c537ee..eb75a22 100644
--- a/core/res/res/drawable-hdpi/divider_vertical_bright_opaque.9.png
+++ b/core/res/res/drawable-hdpi/divider_vertical_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_dark.9.png b/core/res/res/drawable-hdpi/divider_vertical_dark.9.png
index 702b878..55a5e53 100644
--- a/core/res/res/drawable-hdpi/divider_vertical_dark.9.png
+++ b/core/res/res/drawable-hdpi/divider_vertical_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_dark_opaque.9.png b/core/res/res/drawable-hdpi/divider_vertical_dark_opaque.9.png
index 8f35315..60e2cb2 100644
--- a/core/res/res/drawable-hdpi/divider_vertical_dark_opaque.9.png
+++ b/core/res/res/drawable-hdpi/divider_vertical_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_default.9.png b/core/res/res/drawable-hdpi/list_selector_background_default.9.png
new file mode 100644
index 0000000..25c6241
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_selector_background_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_default_light.9.png b/core/res/res/drawable-hdpi/list_selector_background_default_light.9.png
new file mode 100644
index 0000000..c3e69f0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_selector_background_default_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png
index c40233e..ab377d8 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_disabled_light.9.png b/core/res/res/drawable-hdpi/list_selector_background_disabled_light.9.png
new file mode 100644
index 0000000..8edc9cd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_selector_background_disabled_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_focus.9.png b/core/res/res/drawable-hdpi/list_selector_background_focus.9.png
deleted file mode 100644
index d8e16b99..0000000
--- a/core/res/res/drawable-hdpi/list_selector_background_focus.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_focused.9.png b/core/res/res/drawable-hdpi/list_selector_background_focused.9.png
new file mode 100644
index 0000000..60bb454
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_selector_background_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_focused_light.9.png b/core/res/res/drawable-hdpi/list_selector_background_focused_light.9.png
new file mode 100644
index 0000000..60bb454
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_selector_background_focused_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_focused_selected.9.png b/core/res/res/drawable-hdpi/list_selector_background_focused_selected.9.png
new file mode 100644
index 0000000..b527da15
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_selector_background_focused_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png b/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png
index 1676ca7..bd74426 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_longpress_light.9.png b/core/res/res/drawable-hdpi/list_selector_background_longpress_light.9.png
new file mode 100644
index 0000000..fc2ba2e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_selector_background_longpress_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png b/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png
index ba79cf7..d18d6f7 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_pressed_light.9.png b/core/res/res/drawable-hdpi/list_selector_background_pressed_light.9.png
new file mode 100644
index 0000000..00786e5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_selector_background_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_selected.9.png b/core/res/res/drawable-hdpi/list_selector_background_selected.9.png
new file mode 100644
index 0000000..cbf50b3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_selector_background_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_selected_light.9.png b/core/res/res/drawable-hdpi/list_selector_background_selected_light.9.png
new file mode 100644
index 0000000..34ea86e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_selector_background_selected_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_label_background_light.9.png b/core/res/res/drawable-mdpi/btn_check_label_background_light.9.png
deleted file mode 100644
index 79367b8..0000000
--- a/core/res/res/drawable-mdpi/btn_check_label_background_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off.png b/core/res/res/drawable-mdpi/btn_check_off.png
index 5e44c29..56d3861 100644
--- a/core/res/res/drawable-mdpi/btn_check_off.png
+++ b/core/res/res/drawable-mdpi/btn_check_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable.png b/core/res/res/drawable-mdpi/btn_check_off_disable.png
index a603fb1..e012afd 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_focused.png b/core/res/res/drawable-mdpi/btn_check_off_disable_focused.png
index a603fb1..0837bbd 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable_focused.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_dark.png
new file mode 100644
index 0000000..a603fb1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_focused_light.png b/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_check_off_disable_focused_light.png
rename to core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_disable_holo_dark.png
new file mode 100644
index 0000000..a603fb1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_light.png b/core/res/res/drawable-mdpi/btn_check_off_disable_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_check_off_disable_light.png
rename to core/res/res/drawable-mdpi/btn_check_off_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_holo_dark.png
new file mode 100644
index 0000000..5e44c29
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_light.png b/core/res/res/drawable-mdpi/btn_check_off_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_check_off_light.png
rename to core/res/res/drawable-mdpi/btn_check_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_pressed.png b/core/res/res/drawable-mdpi/btn_check_off_pressed.png
index 611bb1d..984dfd7 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png
new file mode 100644
index 0000000..611bb1d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_pressed_light.png b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_check_off_pressed_light.png
rename to core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_selected.png b/core/res/res/drawable-mdpi/btn_check_off_selected.png
index aa28df2..20842d4 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_selected.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_selected_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_selected_holo_dark.png
new file mode 100644
index 0000000..aa28df2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_off_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_selected_light.png b/core/res/res/drawable-mdpi/btn_check_off_selected_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_check_off_selected_light.png
rename to core/res/res/drawable-mdpi/btn_check_off_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on.png b/core/res/res/drawable-mdpi/btn_check_on.png
index 130d562..791ac1d 100644
--- a/core/res/res/drawable-mdpi/btn_check_on.png
+++ b/core/res/res/drawable-mdpi/btn_check_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable.png b/core/res/res/drawable-mdpi/btn_check_on_disable.png
index f19972a..6cb02f3 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_focused.png b/core/res/res/drawable-mdpi/btn_check_on_disable_focused.png
index f19972a..8a73b33 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_focused.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png
new file mode 100644
index 0000000..f19972a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_light.png b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_check_on_disable_focused_light.png
rename to core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disable_holo_dark.png
new file mode 100644
index 0000000..f19972a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_light.png b/core/res/res/drawable-mdpi/btn_check_on_disable_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_check_on_disable_light.png
rename to core/res/res/drawable-mdpi/btn_check_on_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png
new file mode 100644
index 0000000..130d562
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_light.png b/core/res/res/drawable-mdpi/btn_check_on_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_check_on_light.png
rename to core/res/res/drawable-mdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed.png b/core/res/res/drawable-mdpi/btn_check_on_pressed.png
index df753f5..300d64a 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
new file mode 100644
index 0000000..df753f5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_light.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_check_on_pressed_light.png
rename to core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_selected.png b/core/res/res/drawable-mdpi/btn_check_on_selected.png
index 7586881..0b36adb 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_selected.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_selected_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_selected_holo_dark.png
new file mode 100644
index 0000000..7586881
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_on_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_selected_light.png b/core/res/res/drawable-mdpi/btn_check_on_selected_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_check_on_selected_light.png
rename to core/res/res/drawable-mdpi/btn_check_on_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_label_background_light.9.png b/core/res/res/drawable-mdpi/btn_radio_label_background_light.9.png
deleted file mode 100644
index 16e8939..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_label_background_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off.png b/core/res/res/drawable-mdpi/btn_radio_off.png
index 16c1c6b..407632b 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_off_holo_dark.png
new file mode 100644
index 0000000..16c1c6b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_light.png b/core/res/res/drawable-mdpi/btn_radio_off_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_radio_off_light.png
rename to core/res/res/drawable-mdpi/btn_radio_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_pressed.png b/core/res/res/drawable-mdpi/btn_radio_off_pressed.png
index b25217b..d6d8a9d 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_dark.png
new file mode 100644
index 0000000..b25217b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_pressed_light.png b/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_radio_off_pressed_light.png
rename to core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_selected.png b/core/res/res/drawable-mdpi/btn_radio_off_selected.png
index bef7572..53f3e87 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_selected.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_dark.png
new file mode 100644
index 0000000..bef7572
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_selected_light.png b/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_radio_off_selected_light.png
rename to core/res/res/drawable-mdpi/btn_radio_off_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on.png b/core/res/res/drawable-mdpi/btn_radio_on.png
index 4ed7471..25a3ccc 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_on_holo_dark.png
new file mode 100644
index 0000000..4ed7471
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_light.png b/core/res/res/drawable-mdpi/btn_radio_on_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_radio_on_light.png
rename to core/res/res/drawable-mdpi/btn_radio_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_pressed.png b/core/res/res/drawable-mdpi/btn_radio_on_pressed.png
index 7cf91c6..c904a35 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_dark.png
new file mode 100644
index 0000000..7cf91c6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_pressed_light.png b/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_radio_on_pressed_light.png
rename to core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_selected.png b/core/res/res/drawable-mdpi/btn_radio_on_selected.png
index 56f6f5b..78e1fc0 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_selected.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_dark.png
new file mode 100644
index 0000000..56f6f5b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_selected_light.png b/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_light.png
similarity index 100%
rename from core/res/res/drawable-mdpi/btn_radio_on_selected_light.png
rename to core/res/res/drawable-mdpi/btn_radio_on_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_bright.9.png b/core/res/res/drawable-mdpi/divider_horizontal_bright.9.png
index 395227a..41b776b 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_bright.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_bright_opaque.9.png b/core/res/res/drawable-mdpi/divider_horizontal_bright_opaque.9.png
index 5c537ee..eb75a22 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_bright_opaque.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png b/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png
index bf45e38..55a5e53 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_dark_opaque.9.png b/core/res/res/drawable-mdpi/divider_horizontal_dark_opaque.9.png
index 9444f0d..60e2cb2 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_dark_opaque.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_dim_dark.9.png b/core/res/res/drawable-mdpi/divider_horizontal_dim_dark.9.png
index 08838ca..cf34613 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_dim_dark.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_dim_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_vertical_bright.9.png b/core/res/res/drawable-mdpi/divider_vertical_bright.9.png
index 395227a..41b776b 100644
--- a/core/res/res/drawable-mdpi/divider_vertical_bright.9.png
+++ b/core/res/res/drawable-mdpi/divider_vertical_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_vertical_bright_opaque.9.png b/core/res/res/drawable-mdpi/divider_vertical_bright_opaque.9.png
index 5c537ee..eb75a22 100644
--- a/core/res/res/drawable-mdpi/divider_vertical_bright_opaque.9.png
+++ b/core/res/res/drawable-mdpi/divider_vertical_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_vertical_dark.9.png b/core/res/res/drawable-mdpi/divider_vertical_dark.9.png
index 702b878..55a5e53 100644
--- a/core/res/res/drawable-mdpi/divider_vertical_dark.9.png
+++ b/core/res/res/drawable-mdpi/divider_vertical_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_vertical_dark_opaque.9.png b/core/res/res/drawable-mdpi/divider_vertical_dark_opaque.9.png
index 8f35315..60e2cb2 100644
--- a/core/res/res/drawable-mdpi/divider_vertical_dark_opaque.9.png
+++ b/core/res/res/drawable-mdpi/divider_vertical_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_default.9.png b/core/res/res/drawable-mdpi/list_selector_background_default.9.png
new file mode 100644
index 0000000..cac71b0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_selector_background_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_default_light.9.png b/core/res/res/drawable-mdpi/list_selector_background_default_light.9.png
new file mode 100644
index 0000000..bdedffd
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_selector_background_default_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png
index bf970b0..60f19fe 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_disabled_light.9.png b/core/res/res/drawable-mdpi/list_selector_background_disabled_light.9.png
new file mode 100644
index 0000000..bc992612
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_selector_background_disabled_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_focus.9.png b/core/res/res/drawable-mdpi/list_selector_background_focus.9.png
deleted file mode 100644
index c3e24158..0000000
--- a/core/res/res/drawable-mdpi/list_selector_background_focus.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_focused.9.png b/core/res/res/drawable-mdpi/list_selector_background_focused.9.png
new file mode 100644
index 0000000..5b1f195
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_selector_background_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_focused_light.9.png b/core/res/res/drawable-mdpi/list_selector_background_focused_light.9.png
new file mode 100644
index 0000000..5b1f195
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_selector_background_focused_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_focused_selected.9.png b/core/res/res/drawable-mdpi/list_selector_background_focused_selected.9.png
new file mode 100644
index 0000000..e5b0c1d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_selector_background_focused_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png b/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png
index 5cbb251..7817667 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_longpress_light.9.png b/core/res/res/drawable-mdpi/list_selector_background_longpress_light.9.png
new file mode 100644
index 0000000..646fc69
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_selector_background_longpress_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png b/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png
index 02b4e9a..1531d9d 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_pressed_light.9.png b/core/res/res/drawable-mdpi/list_selector_background_pressed_light.9.png
new file mode 100644
index 0000000..fdf6f49
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_selector_background_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_selected.9.png b/core/res/res/drawable-mdpi/list_selector_background_selected.9.png
new file mode 100644
index 0000000..a4ac1e3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_selector_background_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_selected_light.9.png b/core/res/res/drawable-mdpi/list_selector_background_selected_light.9.png
new file mode 100644
index 0000000..d086194
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_selector_background_selected_light.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_check_light.xml b/core/res/res/drawable/btn_check_holo_dark.xml
similarity index 72%
copy from core/res/res/drawable/btn_check_light.xml
copy to core/res/res/drawable/btn_check_holo_dark.xml
index 85f119a..fd85d72 100644
--- a/core/res/res/drawable/btn_check_light.xml
+++ b/core/res/res/drawable/btn_check_holo_dark.xml
@@ -17,49 +17,49 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Enabled states -->
-
+
<item android:state_checked="true" android:state_window_focused="false"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_on_light" />
+ android:drawable="@drawable/btn_check_on_holo_dark" />
<item android:state_checked="false" android:state_window_focused="false"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_off_light" />
+ android:drawable="@drawable/btn_check_off_holo_dark" />
<item android:state_checked="true" android:state_pressed="true"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_on_pressed_light" />
+ android:drawable="@drawable/btn_check_on_pressed_holo_dark" />
<item android:state_checked="false" android:state_pressed="true"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_off_pressed_light" />
+ android:drawable="@drawable/btn_check_off_pressed_holo_dark" />
<item android:state_checked="true" android:state_focused="true"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_on_selected_light" />
+ android:drawable="@drawable/btn_check_on_selected_holo_dark" />
<item android:state_checked="false" android:state_focused="true"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_off_selected_light" />
+ android:drawable="@drawable/btn_check_off_selected_holo_dark" />
<item android:state_checked="false"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_off_light" />
+ android:drawable="@drawable/btn_check_off_holo_dark" />
<item android:state_checked="true"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_on_light" />
+ android:drawable="@drawable/btn_check_on_holo_dark" />
<!-- Disabled states -->
<item android:state_checked="true" android:state_window_focused="false"
- android:drawable="@drawable/btn_check_on_disable_light" />
+ android:drawable="@drawable/btn_check_on_disable_holo_dark" />
<item android:state_checked="false" android:state_window_focused="false"
- android:drawable="@drawable/btn_check_off_disable_light" />
+ android:drawable="@drawable/btn_check_off_disable_holo_dark" />
<item android:state_checked="true" android:state_focused="true"
- android:drawable="@drawable/btn_check_on_disable_focused_light" />
+ android:drawable="@drawable/btn_check_on_disable_focused_holo_dark" />
<item android:state_checked="false" android:state_focused="true"
- android:drawable="@drawable/btn_check_off_disable_focused_light" />
+ android:drawable="@drawable/btn_check_off_disable_focused_holo_dark" />
- <item android:state_checked="false" android:drawable="@drawable/btn_check_off_disable_light" />
- <item android:state_checked="true" android:drawable="@drawable/btn_check_on_disable_light" />
+ <item android:state_checked="false" android:drawable="@drawable/btn_check_off_disable_holo_dark" />
+ <item android:state_checked="true" android:drawable="@drawable/btn_check_on_disable_holo_dark" />
</selector>
diff --git a/core/res/res/drawable/btn_check_light.xml b/core/res/res/drawable/btn_check_holo_light.xml
similarity index 72%
rename from core/res/res/drawable/btn_check_light.xml
rename to core/res/res/drawable/btn_check_holo_light.xml
index 85f119a..4fb16fa 100644
--- a/core/res/res/drawable/btn_check_light.xml
+++ b/core/res/res/drawable/btn_check_holo_light.xml
@@ -17,49 +17,49 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Enabled states -->
-
+
<item android:state_checked="true" android:state_window_focused="false"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_on_light" />
+ android:drawable="@drawable/btn_check_on_holo_light" />
<item android:state_checked="false" android:state_window_focused="false"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_off_light" />
+ android:drawable="@drawable/btn_check_off_holo_light" />
<item android:state_checked="true" android:state_pressed="true"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_on_pressed_light" />
+ android:drawable="@drawable/btn_check_on_pressed_holo_light" />
<item android:state_checked="false" android:state_pressed="true"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_off_pressed_light" />
+ android:drawable="@drawable/btn_check_off_pressed_holo_light" />
<item android:state_checked="true" android:state_focused="true"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_on_selected_light" />
+ android:drawable="@drawable/btn_check_on_selected_holo_light" />
<item android:state_checked="false" android:state_focused="true"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_off_selected_light" />
+ android:drawable="@drawable/btn_check_off_selected_holo_light" />
<item android:state_checked="false"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_off_light" />
+ android:drawable="@drawable/btn_check_off_holo_light" />
<item android:state_checked="true"
android:state_enabled="true"
- android:drawable="@drawable/btn_check_on_light" />
+ android:drawable="@drawable/btn_check_on_holo_light" />
<!-- Disabled states -->
<item android:state_checked="true" android:state_window_focused="false"
- android:drawable="@drawable/btn_check_on_disable_light" />
+ android:drawable="@drawable/btn_check_on_disable_holo_light" />
<item android:state_checked="false" android:state_window_focused="false"
- android:drawable="@drawable/btn_check_off_disable_light" />
+ android:drawable="@drawable/btn_check_off_disable_holo_light" />
<item android:state_checked="true" android:state_focused="true"
- android:drawable="@drawable/btn_check_on_disable_focused_light" />
+ android:drawable="@drawable/btn_check_on_disable_focused_holo_light" />
<item android:state_checked="false" android:state_focused="true"
- android:drawable="@drawable/btn_check_off_disable_focused_light" />
+ android:drawable="@drawable/btn_check_off_disable_focused_holo_light" />
- <item android:state_checked="false" android:drawable="@drawable/btn_check_off_disable_light" />
- <item android:state_checked="true" android:drawable="@drawable/btn_check_on_disable_light" />
+ <item android:state_checked="false" android:drawable="@drawable/btn_check_off_disable_holo_light" />
+ <item android:state_checked="true" android:drawable="@drawable/btn_check_on_disable_holo_light" />
</selector>
diff --git a/core/res/res/drawable/btn_radio_light.xml b/core/res/res/drawable/btn_radio_holo_dark.xml
similarity index 72%
rename from core/res/res/drawable/btn_radio_light.xml
rename to core/res/res/drawable/btn_radio_holo_dark.xml
index 51c930b..8984f6d 100644
--- a/core/res/res/drawable/btn_radio_light.xml
+++ b/core/res/res/drawable/btn_radio_holo_dark.xml
@@ -16,20 +16,20 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:state_window_focused="false"
- android:drawable="@drawable/btn_radio_on_light" />
+ android:drawable="@drawable/btn_radio_on_holo_dark" />
<item android:state_checked="false" android:state_window_focused="false"
- android:drawable="@drawable/btn_radio_off_light" />
-
+ android:drawable="@drawable/btn_radio_off_holo_dark" />
+
<item android:state_checked="true" android:state_pressed="true"
- android:drawable="@drawable/btn_radio_on_pressed_light" />
+ android:drawable="@drawable/btn_radio_on_pressed_holo_dark" />
<item android:state_checked="false" android:state_pressed="true"
- android:drawable="@drawable/btn_radio_off_pressed_light" />
+ android:drawable="@drawable/btn_radio_off_pressed_holo_dark" />
<item android:state_checked="true" android:state_focused="true"
- android:drawable="@drawable/btn_radio_on_selected_light" />
+ android:drawable="@drawable/btn_radio_on_selected_holo_dark" />
<item android:state_checked="false" android:state_focused="true"
- android:drawable="@drawable/btn_radio_off_selected_light" />
+ android:drawable="@drawable/btn_radio_off_selected_holo_dark" />
- <item android:state_checked="false" android:drawable="@drawable/btn_radio_off_light" />
- <item android:state_checked="true" android:drawable="@drawable/btn_radio_on_light" />
+ <item android:state_checked="false" android:drawable="@drawable/btn_radio_off_holo_dark" />
+ <item android:state_checked="true" android:drawable="@drawable/btn_radio_on_holo_dark" />
</selector>
diff --git a/core/res/res/drawable/btn_radio_light.xml b/core/res/res/drawable/btn_radio_holo_light.xml
similarity index 72%
copy from core/res/res/drawable/btn_radio_light.xml
copy to core/res/res/drawable/btn_radio_holo_light.xml
index 51c930b..001508c 100644
--- a/core/res/res/drawable/btn_radio_light.xml
+++ b/core/res/res/drawable/btn_radio_holo_light.xml
@@ -16,20 +16,20 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:state_window_focused="false"
- android:drawable="@drawable/btn_radio_on_light" />
+ android:drawable="@drawable/btn_radio_on_holo_light" />
<item android:state_checked="false" android:state_window_focused="false"
- android:drawable="@drawable/btn_radio_off_light" />
-
+ android:drawable="@drawable/btn_radio_off_holo_light" />
+
<item android:state_checked="true" android:state_pressed="true"
- android:drawable="@drawable/btn_radio_on_pressed_light" />
+ android:drawable="@drawable/btn_radio_on_pressed_holo_light" />
<item android:state_checked="false" android:state_pressed="true"
- android:drawable="@drawable/btn_radio_off_pressed_light" />
+ android:drawable="@drawable/btn_radio_off_pressed_holo_light" />
<item android:state_checked="true" android:state_focused="true"
- android:drawable="@drawable/btn_radio_on_selected_light" />
+ android:drawable="@drawable/btn_radio_on_selected_holo_light" />
<item android:state_checked="false" android:state_focused="true"
- android:drawable="@drawable/btn_radio_off_selected_light" />
+ android:drawable="@drawable/btn_radio_off_selected_holo_light" />
- <item android:state_checked="false" android:drawable="@drawable/btn_radio_off_light" />
- <item android:state_checked="true" android:drawable="@drawable/btn_radio_on_light" />
+ <item android:state_checked="false" android:drawable="@drawable/btn_radio_off_holo_light" />
+ <item android:state_checked="true" android:drawable="@drawable/btn_radio_on_holo_light" />
</selector>
diff --git a/core/res/res/drawable/list_selected_background.xml b/core/res/res/drawable/list_selected_background.xml
new file mode 100644
index 0000000..2bb6594
--- /dev/null
+++ b/core/res/res/drawable/list_selected_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_focused="true" android:state_checked="true" android:drawable="@drawable/list_selector_background_focused_selected" />
+ <item android:state_focused="false" android:state_checked="true" android:drawable="@drawable/list_selector_background_selected" />
+
+</selector>
diff --git a/core/res/res/drawable/list_selected_background_light.xml b/core/res/res/drawable/list_selected_background_light.xml
new file mode 100644
index 0000000..15fc1cb
--- /dev/null
+++ b/core/res/res/drawable/list_selected_background_light.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_focused="true" android:state_checked="true" android:drawable="@drawable/list_selector_background_focused_selected" />
+ <item android:state_focused="false" android:state_checked="true" android:drawable="@drawable/list_selector_background_selected_light" />
+
+</selector>
diff --git a/core/res/res/drawable/list_selector_background.xml b/core/res/res/drawable/list_selector_background.xml
index bca996c..0a51152 100644
--- a/core/res/res/drawable/list_selector_background.xml
+++ b/core/res/res/drawable/list_selector_background.xml
@@ -16,22 +16,14 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_window_focused="false"
- android:drawable="@color/transparent" />
+ <item android:state_window_focused="false" android:drawable="@color/transparent" />
<!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
- <item android:state_focused="true" android:state_enabled="false"
- android:state_pressed="true"
- android:drawable="@drawable/list_selector_background_disabled" />
- <item android:state_focused="true" android:state_enabled="false"
- android:drawable="@drawable/list_selector_background_disabled" />
-
- <item android:state_focused="true" android:state_pressed="true"
- android:drawable="@drawable/list_selector_background_transition" />
- <item android:state_focused="false" android:state_pressed="true"
- android:drawable="@drawable/list_selector_background_transition" />
-
- <item android:state_focused="true"
- android:drawable="@drawable/list_selector_background_focus" />
-
+ <item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/list_selector_background_disabled" />
+ <item android:state_focused="true" android:state_enabled="false" android:drawable="@drawable/list_selector_background_disabled" />
+ <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition" />
+ <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition" />
+ <item android:state_focused="true" android:drawable="@drawable/list_selector_background_focused" />
+ <item android:drawable="@drawable/list_selector_background_default" />
+
</selector>
diff --git a/core/res/res/drawable/list_selector_background_light.xml b/core/res/res/drawable/list_selector_background_light.xml
new file mode 100644
index 0000000..9b7980c
--- /dev/null
+++ b/core/res/res/drawable/list_selector_background_light.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_window_focused="false" android:drawable="@color/transparent" />
+
+ <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
+ <item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/list_selector_background_disabled_light" />
+ <item android:state_focused="true" android:state_enabled="false" android:drawable="@drawable/list_selector_background_disabled_light" />
+ <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition_light" />
+ <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition_light" />
+ <item android:state_focused="true" android:drawable="@drawable/list_selector_background_focused_light" />
+ <item android:drawable="@drawable/list_selector_background_default_light" />
+
+</selector>
diff --git a/core/res/res/drawable/list_selector_background_transition_light.xml b/core/res/res/drawable/list_selector_background_transition_light.xml
new file mode 100644
index 0000000..634f895
--- /dev/null
+++ b/core/res/res/drawable/list_selector_background_transition_light.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<transition xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@android:drawable/list_selector_background_pressed_light" />
+ <item android:drawable="@android:drawable/list_selector_background_longpress_light" />
+</transition>
diff --git a/core/res/res/layout/select_dialog_multichoice.xml b/core/res/res/layout/select_dialog_multichoice.xml
index 5785d3b..b646a4c 100644
--- a/core/res/res/layout/select_dialog_multichoice.xml
+++ b/core/res/res/layout/select_dialog_multichoice.xml
@@ -24,7 +24,7 @@
android:gravity="center_vertical"
android:paddingLeft="12dip"
android:paddingRight="7dip"
- android:checkMark="@android:drawable/btn_check"
+ android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:ellipsize="marquee"
/>
diff --git a/core/res/res/layout/select_dialog_singlechoice.xml b/core/res/res/layout/select_dialog_singlechoice.xml
index 3560fee..c3c2073 100644
--- a/core/res/res/layout/select_dialog_singlechoice.xml
+++ b/core/res/res/layout/select_dialog_singlechoice.xml
@@ -24,6 +24,6 @@
android:gravity="center_vertical"
android:paddingLeft="12dip"
android:paddingRight="7dip"
- android:checkMark="@android:drawable/btn_radio"
+ android:checkMark="?android:attr/listChoiceIndicatorSingle"
android:ellipsize="marquee"
/>
diff --git a/core/res/res/layout/simple_selectable_list_item.xml b/core/res/res/layout/simple_selectable_list_item.xml
new file mode 100644
index 0000000..518bcd0
--- /dev/null
+++ b/core/res/res/layout/simple_selectable_list_item.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:gravity="center_vertical"
+ android:background="?android:attr/listChoiceBackgroundIndicator"
+ android:paddingLeft="6dip"
+ android:paddingRight="9dip"
+/>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 3de378b..1cbfbba 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1079,11 +1079,9 @@
<skip />
<!-- no translation found for cut (5845613239192595662) -->
<skip />
- <!-- no translation found for cutAll (4474519683293791451) -->
<skip />
<!-- no translation found for copy (8603721575469529820) -->
<skip />
- <!-- no translation found for copyAll (4777548804630476932) -->
<skip />
<!-- no translation found for paste (6458036735811828538) -->
<skip />
diff --git a/core/res/res/values-en-rSG/strings.xml b/core/res/res/values-en-rSG/strings.xml
index 2ec6b0b..09a8490 100644
--- a/core/res/res/values-en-rSG/strings.xml
+++ b/core/res/res/values-en-rSG/strings.xml
@@ -1074,11 +1074,9 @@
<skip />
<!-- no translation found for cut (5845613239192595662) -->
<skip />
- <!-- no translation found for cutAll (4474519683293791451) -->
<skip />
<!-- no translation found for copy (8603721575469529820) -->
<skip />
- <!-- no translation found for copyAll (4777548804630476932) -->
<skip />
<!-- no translation found for paste (6458036735811828538) -->
<skip />
diff --git a/core/res/res/values-en-rUS/strings.xml b/core/res/res/values-en-rUS/strings.xml
index 05f30fc..fdc0d69 100644
--- a/core/res/res/values-en-rUS/strings.xml
+++ b/core/res/res/values-en-rUS/strings.xml
@@ -1115,11 +1115,9 @@
<skip />
<!-- no translation found for cut (5845613239192595662) -->
<skip />
- <!-- no translation found for cutAll (4474519683293791451) -->
<skip />
<!-- no translation found for copy (8603721575469529820) -->
<skip />
- <!-- no translation found for copyAll (4777548804630476932) -->
<skip />
<!-- no translation found for paste (6458036735811828538) -->
<skip />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index fe8a816..be27528 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -148,6 +148,9 @@
<!-- Drawable to use for single choice indicators. -->
<attr name="listChoiceIndicatorSingle" format="reference" />
+ <!-- Drawable used as a background for selected list items. -->
+ <attr name="listChoiceBackgroundIndicator" format="reference" />
+
<!-- ============= -->
<!-- Button styles -->
<!-- ============= -->
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 30c5184..e9a4ca3 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -37,18 +37,18 @@
<color name="black">#ff000000</color>
<color name="transparent">#00000000</color>
<color name="background_dark">#ff101010</color>
- <color name="bright_foreground_dark">#ffefefef</color>
+ <color name="background_light">#ffefefef</color>
+ <color name="bright_foreground_dark">@android:color/background_light</color>
+ <color name="bright_foreground_light">@android:color/background_dark</color>
<color name="bright_foreground_dark_disabled">#80ffffff</color>
- <color name="bright_foreground_dark_inverse">@android:color/dim_foreground_dark</color>
+ <color name="bright_foreground_light_disabled">#80000000</color>
+ <color name="bright_foreground_dark_inverse">@android:color/bright_foreground_light</color>
+ <color name="bright_foreground_light_inverse">@android:color/bright_foreground_dark</color>
<color name="dim_foreground_dark">#bebebe</color>
<color name="dim_foreground_dark_disabled">#80bebebe</color>
<color name="dim_foreground_dark_inverse">#323232</color>
<color name="dim_foreground_dark_inverse_disabled">#80323232</color>
<color name="hint_foreground_dark">#808080</color>
- <color name="background_light">@android:color/bright_foreground_dark</color>
- <color name="bright_foreground_light">@android:color/background_dark</color>
- <color name="bright_foreground_light_inverse">@android:color/bright_foreground_dark</color>
- <color name="bright_foreground_light_disabled">#80000000</color>
<color name="dim_foreground_light">#323232</color>
<color name="dim_foreground_light_disabled">#80323232</color>
<color name="dim_foreground_light_inverse">#bebebe</color>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ea5c158..ddd3c00 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1329,6 +1329,8 @@
<public type="anim" name="animator_fade_in" />
<public type="anim" name="animator_fade_out" />
+ <public type="attr" name="listChoiceBackgroundIndicator" id="0x01010330" />
+
<public type="id" name="home" />
<!-- Context menu ID for the "Select text..." menu item to switch to text
selection context mode in text views. -->
@@ -1347,18 +1349,15 @@
the base class. -->
<public type="layout" name="list_content" />
- <!-- A dark holographic theme. -->
<public type="style" name="Theme.Holo" />
- <!-- A light holographic theme. -->
<public type="style" name="Theme.Light.Holo" />
- <!-- Variant of the holographic (dark) theme with no title bar -->
- <public type="style" name="Theme.Holo.NoTitleBar" />
- <!-- Variant of the holographic (dark) theme that has no title bar and fills the entire screen -->
- <public type="style" name="Theme.Holo.NoTitleBar.Fullscreen" />
- <!-- Variant of the holographic light theme with no title bar -->
- <public type="style" name="Theme.Light.Holo.NoTitleBar" />
- <!-- Variant of the holographic light theme that has no title bar and fills the entire screen -->
- <public type="style" name="Theme.Light.Holo.NoTitleBar.Fullscreen" />
+ <public type="style" name="Theme.Holo.NoActionBar" />
+ <public type="style" name="Theme.Holo.NoActionBar.Fullscreen" />
+ <public type="style" name="Theme.Light.Holo.NoActionBar" />
+ <public type="style" name="Theme.Light.Holo.NoActionBar.Fullscreen" />
+
+ <!-- A simple ListView item layout which can contain text and support (single or multiple) item selection. -->
+ <public type="layout" name="simple_selectable_list_item" id="0x01090022" />
<public type="string" name="selectTextMode" id="0x01040030" />
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 37b66d3..6964808 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -280,22 +280,12 @@
<style name="Widget.CompoundButton.CheckBox">
<item name="android:background">@android:drawable/btn_check_label_background</item>
- <item name="android:button">@android:drawable/btn_check</item>
- </style>
-
- <style name="Widget.CompoundButton.CheckBox.Inverse">
- <item name="android:background">@android:drawable/btn_check_label_background_light</item>
- <item name="android:button">@android:drawable/btn_check_light</item>
+ <item name="android:button">?android:attr/listChoiceIndicatorMultiple</item>
</style>
<style name="Widget.CompoundButton.RadioButton">
<item name="android:background">@android:drawable/btn_radio_label_background</item>
- <item name="android:button">@android:drawable/btn_radio</item>
- </style>
-
- <style name="Widget.CompoundButton.RadioButton.Inverse">
- <item name="android:background">@android:drawable/btn_radio_label_background_light</item>
- <item name="android:button">@android:drawable/btn_radio_light</item>
+ <item name="android:button">?android:attr/listChoiceIndicatorSingle</item>
</style>
<style name="Widget.CompoundButton.Star">
@@ -503,7 +493,7 @@
</style>
<style name="Widget.DropDownItem.Spinner">
- <item name="android:checkMark">@android:drawable/btn_radio</item>
+ <item name="android:checkMark">?android:attr/listChoiceIndicatorSingle</item>
</style>
<style name="Widget.ScrollView">
@@ -523,7 +513,7 @@
</style>
<style name="Widget.ListView.White" parent="Widget.AbsListView">
- <item name="android:listSelector">@android:drawable/list_selector_background</item>
+ <item name="android:listSelector">@android:drawable/list_selector_background_light</item>
<item name="android:cacheColorHint">?android:attr/colorBackgroundCacheHint</item>
<item name="android:divider">@android:drawable/divider_horizontal_bright_opaque</item>
</style>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index c78705b..3ebe7cb 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -92,9 +92,11 @@
<item name="listDivider">@drawable/divider_horizontal_dark</item>
<item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator</item>
- <item name="listChoiceIndicatorSingle">@android:drawable/btn_radio</item>
+ <item name="listChoiceIndicatorSingle">@android:drawable/btn_radio</item>
<item name="listChoiceIndicatorMultiple">@android:drawable/btn_check</item>
+ <item name="listChoiceBackgroundIndicator">@android:drawable/list_selected_background</item>
+
<item name="expandableListPreferredItemPaddingLeft">40dip</item>
<item name="expandableListPreferredChildPaddingLeft">
?android:attr/expandableListPreferredItemPaddingLeft</item>
@@ -168,8 +170,8 @@
<item name="progressBarStyleSmallTitle">@android:style/Widget.ProgressBar.Small.Title</item>
<item name="progressBarStyleLarge">@android:style/Widget.ProgressBar.Large</item>
<item name="progressBarStyleInverse">@android:style/Widget.ProgressBar.Inverse</item>
- <item name="progressBarStyleSmallInverse">@android:style/Widget.ProgressBar.Small.Inverse</item>
- <item name="progressBarStyleLargeInverse">@android:style/Widget.ProgressBar.Large.Inverse</item>
+ <item name="progressBarStyleSmallInverse">@android:style/Widget.ProgressBar.Small.Inverse</item>
+ <item name="progressBarStyleLargeInverse">@android:style/Widget.ProgressBar.Large.Inverse</item>
<item name="seekBarStyle">@android:style/Widget.SeekBar</item>
<item name="ratingBarStyle">@android:style/Widget.RatingBar</item>
<item name="ratingBarStyleIndicator">@android:style/Widget.RatingBar.Indicator</item>
@@ -261,29 +263,25 @@
<item name="textColorLinkInverse">@android:color/link_text_dark</item>
<item name="editTextColor">?android:attr/textColorPrimary</item>
+ <item name="listChoiceBackgroundIndicator">@android:drawable/list_selected_background_light</item>
+
<item name="popupWindowStyle">@android:style/Widget.PopupWindow</item>
<item name="textCheckMark">@android:drawable/indicator_check_mark_light</item>
<item name="textCheckMarkInverse">@android:drawable/indicator_check_mark_dark</item>
- <!-- List attributes -->
- <item name="listChoiceIndicatorSingle">@android:drawable/btn_radio_light</item>
- <item name="listChoiceIndicatorMultiple">@android:drawable/btn_check_light</item>
-
- <!-- Widget styles -->
- <item name="checkboxStyle">@android:style/Widget.CompoundButton.CheckBox.Inverse</item>
<item name="gestureOverlayViewStyle">@android:style/Widget.GestureOverlayView.White</item>
<item name="expandableListViewStyle">@android:style/Widget.ExpandableListView.White</item>
<item name="listViewStyle">@android:style/Widget.ListView.White</item>
<item name="listDivider">@drawable/divider_horizontal_bright</item>
<item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator.White</item>
+
<item name="progressBarStyle">@android:style/Widget.ProgressBar.Inverse</item>
<item name="progressBarStyleSmall">@android:style/Widget.ProgressBar.Small.Inverse</item>
<item name="progressBarStyleLarge">@android:style/Widget.ProgressBar.Large.Inverse</item>
<item name="progressBarStyleInverse">@android:style/Widget.ProgressBar</item>
<item name="progressBarStyleSmallInverse">@android:style/Widget.ProgressBar.Small</item>
- <item name="progressBarStyleLargeInverse">@android:style/Widget.ProgressBar.Large</item>
- <item name="radioButtonStyle">@android:style/Widget.CompoundButton.RadioButton.Inverse</item>
+ <item name="progressBarStyleLargeInverse">@android:style/Widget.ProgressBar.Large</item>
</style>
<!-- Variant of the light theme with no title bar -->
@@ -575,35 +573,52 @@
<item name="android:windowActionModeOverlay">true</item>
</style>
- <!-- New Honeycomb holographic theme. Dark version -->
+ <!-- New Honeycomb holographic theme. Dark version. The widgets in the
+ holographic theme are translucent on their brackground, so applications
+ must ensure that any background they use with this theme is itself
+ dark; otherwise, it will be difficult to see the widgets. The new
+ UI style also includes a full action bar by default. -->
<style name="Theme.Holo">
<item name="editTextBackground">@android:drawable/edit_text_holo_dark</item>
<item name="editTextColor">?android:attr/textColorPrimary</item>
+ <item name="android:windowActionBar">true</item>
+ <item name="listChoiceIndicatorSingle">@android:drawable/btn_radio_holo_dark</item>
+ <item name="listChoiceIndicatorMultiple">@android:drawable/btn_check_holo_dark</item>
</style>
- <!-- New Honeycomb holographic theme. Light version -->
+ <!-- New Honeycomb holographic theme. Light version. The widgets in the
+ holographic theme are translucent on their brackground, so applications
+ must ensure that any background they use with this theme is itself
+ light; otherwise, it will be difficult to see the widgets. The new
+ UI style also includes a full action bar by default. -->
<style name="Theme.Light.Holo">
<item name="editTextBackground">@android:drawable/edit_text_holo_light</item>
+ <item name="listChoiceIndicatorSingle">@android:drawable/btn_radio_holo_light</item>
+ <item name="listChoiceIndicatorMultiple">@android:drawable/btn_check_holo_light</item>
</style>
- <!-- Variant of the holo (dark) theme with no title bar -->
- <style name="Theme.Holo.NoTitleBar">
+ <!-- Variant of the holographic (dark) theme with no action bar. -->
+ <style name="Theme.Holo.NoActionBar">
+ <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
- <!-- Variant of the holo (dark) theme that has no title bar and fills the entire screen -->
- <style name="Theme.Holo.NoTitleBar.Fullscreen">
+ <!-- Variant of the holographic (dark) theme that has no title bar and fills
+ the entire screen -->
+ <style name="Theme.Holo.NoActionBar.Fullscreen">
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
- <!-- Variant of the holo light theme with no title bar -->
- <style name="Theme.Light.Holo.NoTitleBar">
+ <!-- Variant of the holographic light theme with no action bar -->
+ <style name="Theme.Light.Holo.NoActionBar">
+ <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
- <!-- Variant of the holo light theme that has no title bar and fills the entire screen -->
- <style name="Theme.Light.Holo.NoTitleBar.Fullscreen">
+ <!-- Variant of the holographic light theme that has no title bar and fills
+ the entire screen -->
+ <style name="Theme.Light.Holo.NoActionBar.Fullscreen">
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
index dc5613e..86eda71 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
@@ -19,8 +19,11 @@
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
+import android.database.DatabaseErrorHandler;
import android.database.DatabaseUtils;
+import android.database.DefaultDatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteStatement;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
@@ -41,6 +44,7 @@
private static final int INSERT = 1;
private static final int UPDATE = 2;
private static final int DELETE = 3;
+ private static final String DB_NAME = "database_test.db";
@Override
protected void setUp() throws Exception {
@@ -61,7 +65,7 @@
private void dbSetUp() throws Exception {
File dbDir = getContext().getDir(this.getClass().getName(), Context.MODE_PRIVATE);
- mDatabaseFile = new File(dbDir, "database_test.db");
+ mDatabaseFile = new File(dbDir, DB_NAME);
if (mDatabaseFile.exists()) {
mDatabaseFile.delete();
}
@@ -860,7 +864,7 @@
"select count(*) from " + TEST_TABLE, null));
// query in a different thread. but since the transaction is started using
// execSQ() instead of beginTransaction(), cursor's query is considered part of
- // the same ransaction - and hence it should see the above inserted row
+ // the same transaction - and hence it should see the above inserted row
Thread t = new Thread() {
@Override public void run() {
c1.requery();
@@ -878,11 +882,11 @@
/**
* This test is same as {@link #testTransactionAndWalInterplay2()} except the following:
- * instead of commiting the data, do rollback and make sure the data seen by the query
+ * instead of committing the data, do rollback and make sure the data seen by the query
* within the transaction is now gone.
*/
@SmallTest
- public void testTransactionAndWalInterplay3() throws InterruptedException {
+ public void testTransactionAndWalInterplay3() {
createTableAndClearCache();
mDatabase.execSQL("INSERT into " + TEST_TABLE + " values(10, 999);");
String sql = "select * from " + TEST_TABLE;
@@ -909,4 +913,36 @@
"select count(*) from " + TEST_TABLE, null));
c.close();
}
+
+ /**
+ * http://b/issue?id=2943028
+ * SQLiteOpenHelper maintains a Singleton even if it is in bad state.
+ */
+ @SmallTest
+ public void testCloseAndReopen() {
+ mDatabase.close();
+ TestOpenHelper helper = new TestOpenHelper(getContext(), DB_NAME, null,
+ CURRENT_DATABASE_VERSION, new DefaultDatabaseErrorHandler());
+ mDatabase = helper.getWritableDatabase();
+ createTableAndClearCache();
+ mDatabase.execSQL("INSERT into " + TEST_TABLE + " values(10, 999);");
+ Cursor c = mDatabase.query(TEST_TABLE, new String[]{"i", "j"}, null, null, null, null, null);
+ assertEquals(1, c.getCount());
+ c.close();
+ mDatabase.close();
+ assertFalse(mDatabase.isOpen());
+ mDatabase = helper.getReadableDatabase();
+ assertTrue(mDatabase.isOpen());
+ c = mDatabase.query(TEST_TABLE, new String[]{"i", "j"}, null, null, null, null, null);
+ assertEquals(1, c.getCount());
+ c.close();
+ }
+ private class TestOpenHelper extends SQLiteOpenHelper {
+ public TestOpenHelper(Context context, String name, CursorFactory factory, int version,
+ DatabaseErrorHandler errorHandler) {
+ super(context, name, factory, version, errorHandler);
+ }
+ @Override public void onCreate(SQLiteDatabase db) {}
+ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
+ }
}
diff --git a/core/tests/coretests/src/android/net/http/HttpsThroughHttpProxyTest.java b/core/tests/coretests/src/android/net/http/HttpsThroughHttpProxyTest.java
index f3b7c06..95aad91 100644
--- a/core/tests/coretests/src/android/net/http/HttpsThroughHttpProxyTest.java
+++ b/core/tests/coretests/src/android/net/http/HttpsThroughHttpProxyTest.java
@@ -22,8 +22,8 @@
import java.io.StringWriter;
import java.util.Arrays;
import java.util.List;
-import javax.net.ssl.TestSSLContext;
import junit.framework.TestCase;
+import libcore.javax.net.ssl.TestSSLContext;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
diff --git a/core/tests/coretests/src/android/os/MessageQueueTest.java b/core/tests/coretests/src/android/os/MessageQueueTest.java
index b7c2d1f..f82bfce 100644
--- a/core/tests/coretests/src/android/os/MessageQueueTest.java
+++ b/core/tests/coretests/src/android/os/MessageQueueTest.java
@@ -41,6 +41,10 @@
}
public void handleMessage(Message msg) {
+ if (!msg.isInUse()) {
+ failure(new RuntimeException(
+ "msg.isInuse is false, should always be true, #" + msg.what));
+ }
if (mCount <= mLastMessage) {
if (msg.what != mCount) {
failure(new RuntimeException(
@@ -99,5 +103,174 @@
tester.doTest(1000);
}
-}
+ private static class TestFieldIntegrityHandler extends TestHandlerThread {
+ Handler mHandler;
+ int mLastMessage;
+ int mCount;
+
+ public TestFieldIntegrityHandler() {
+ }
+
+ public void go() {
+ mHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ TestFieldIntegrityHandler.this.handleMessage(msg);
+ }
+ };
+ }
+
+ public void handleMessage(Message msg) {
+ if (!msg.isInUse()) {
+ failure(new RuntimeException(
+ "msg.isInuse is false, should always be true, #" + msg.what));
+ }
+ if (mCount <= mLastMessage) {
+ if (msg.what != mCount) {
+ failure(new RuntimeException(
+ "Expected message #" + mCount
+ + ", received #" + msg.what));
+ } else if (mCount == mLastMessage) {
+ success();
+ }
+ mCount++;
+ } else {
+ failure(new RuntimeException(
+ "Message received after done, #" + msg.what));
+ }
+ }
+ }
+
+ @MediumTest
+ public void testFieldIntegrity() throws Exception {
+
+ TestHandlerThread tester = new TestFieldIntegrityHandler() {
+ Bundle mBundle;
+
+ public void go() {
+ super.go();
+ mLastMessage = 1;
+ mCount = 0;
+ mHandler.sendMessage(mHandler.obtainMessage(0));
+ }
+
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ if (msg.what == 0) {
+ msg.flags = -1;
+ msg.what = 1;
+ msg.arg1 = 456;
+ msg.arg2 = 789;
+ msg.obj = this;
+ msg.replyTo = null;
+ mBundle = new Bundle();
+ msg.data = mBundle;
+ msg.data.putString("key", "value");
+
+ Message newMsg = mHandler.obtainMessage();
+ newMsg.copyFrom(msg);
+ if (newMsg.isInUse() != false) {
+ failure(new RuntimeException(
+ "newMsg.isInUse is true should be false after copyFrom"));
+ }
+ if (newMsg.flags != 0) {
+ failure(new RuntimeException(String.format(
+ "newMsg.flags is %d should be 0 after copyFrom", newMsg.flags)));
+ }
+ if (newMsg.what != 1) {
+ failure(new RuntimeException(String.format(
+ "newMsg.what is %d should be %d after copyFrom", newMsg.what, 1)));
+ }
+ if (newMsg.arg1 != 456) {
+ failure(new RuntimeException(String.format(
+ "newMsg.arg1 is %d should be %d after copyFrom", msg.arg1, 456)));
+ }
+ if (newMsg.arg2 != 789) {
+ failure(new RuntimeException(String.format(
+ "newMsg.arg2 is %d should be %d after copyFrom", msg.arg2, 789)));
+ }
+ if (newMsg.obj != this) {
+ failure(new RuntimeException(
+ "newMsg.obj should be 'this' after copyFrom"));
+ }
+ if (newMsg.replyTo != null) {
+ failure(new RuntimeException(
+ "newMsg.replyTo should be null after copyFrom"));
+ }
+ if (newMsg.data == mBundle) {
+ failure(new RuntimeException(
+ "newMsg.data should NOT be mBundle after copyFrom"));
+ }
+ if (!newMsg.data.getString("key").equals(mBundle.getString("key"))) {
+ failure(new RuntimeException(String.format(
+ "newMsg.data.getString(\"key\") is %s and does not equal" +
+ " mBundle.getString(\"key\") which is %s after copyFrom",
+ newMsg.data.getString("key"), mBundle.getString("key"))));
+ }
+ if (newMsg.when != 0) {
+ failure(new RuntimeException(String.format(
+ "newMsg.when is %d should be 0 after copyFrom", newMsg.when)));
+ }
+ if (newMsg.target != mHandler) {
+ failure(new RuntimeException(
+ "newMsg.target is NOT mHandler after copyFrom"));
+ }
+ if (newMsg.callback != null) {
+ failure(new RuntimeException(
+ "newMsg.callback is NOT null after copyFrom"));
+ }
+
+ mHandler.sendMessage(newMsg);
+ } else if (msg.what == 1) {
+ if (msg.isInUse() != true) {
+ failure(new RuntimeException(String.format(
+ "msg.isInUse is false should be true after when processing %d",
+ msg.what)));
+ }
+ if (msg.arg1 != 456) {
+ failure(new RuntimeException(String.format(
+ "msg.arg1 is %d should be %d when processing # %d",
+ msg.arg1, 456, msg.what)));
+ }
+ if (msg.arg2 != 789) {
+ failure(new RuntimeException(String.format(
+ "msg.arg2 is %d should be %d when processing # %d",
+ msg.arg2, 789, msg.what)));
+ }
+ if (msg.obj != this) {
+ failure(new RuntimeException(String.format(
+ "msg.obj should be 'this' when processing # %d", msg.what)));
+ }
+ if (msg.replyTo != null) {
+ failure(new RuntimeException(String.format(
+ "msg.replyTo should be null when processing # %d", msg.what)));
+ }
+ if (!msg.data.getString("key").equals(mBundle.getString("key"))) {
+ failure(new RuntimeException(String.format(
+ "msg.data.getString(\"key\") is %s and does not equal" +
+ " mBundle.getString(\"key\") which is %s when processing # %d",
+ msg.data.getString("key"), mBundle.getString("key"), msg.what)));
+ }
+ if (msg.when != 0) {
+ failure(new RuntimeException(String.format(
+ "msg.when is %d should be 0 when processing # %d",
+ msg.when, msg.what)));
+ }
+ if (msg.target != null) {
+ failure(new RuntimeException(String.format(
+ "msg.target is NOT null when processing # %d", msg.what)));
+ }
+ if (msg.callback != null) {
+ failure(new RuntimeException(String.format(
+ "msg.callback is NOT null when processing # %d", msg.what)));
+ }
+ } else {
+ failure(new RuntimeException(String.format(
+ "Unexpected msg.what is %d" + msg.what)));
+ }
+ }
+ };
+
+ tester.doTest(1000);
+ }
+}
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index d0318cf..35ce17e 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -220,9 +220,16 @@
<li><a style="color:gray;">Accelerometer</a></li>
</ul>
</li> -->
- <li><a href="<?cs var:toroot ?>guide/topics/location/index.html">
- <span class="en">Location and Maps</span>
- </a></li>
+ <li class="toggle-list">
+ <div><a href="<?cs var:toroot ?>guide/topics/location/index.html">
+ <span class="en">Location and Maps</span>
+ </a></div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>guide/topics/location/obtaining-user-location.html">
+ <span class="en">Obtaining User Location</span>
+ </a> <span class="new">new!</span></li>
+ </ul>
+ </li>
<!--<li class="toggle-list">
<div><a style="color:gray;">Wireless Controls</a></div>
<ul>
diff --git a/docs/html/guide/topics/fundamentals.jd b/docs/html/guide/topics/fundamentals.jd
index f780e7c..6d6abd8 100644
--- a/docs/html/guide/topics/fundamentals.jd
+++ b/docs/html/guide/topics/fundamentals.jd
@@ -770,9 +770,9 @@
</p>
<p>
-For more on launch modes, see the description of the
-<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>
-element.
+For more on launch modes, see the description of the <code><a
+href="{@docRoot}guide/topics/manifest/activity-element.html#lmode"><activity></a></code>
+element.
</p>
diff --git a/docs/html/guide/topics/location/index.jd b/docs/html/guide/topics/location/index.jd
index e988ecb..5f98902 100644
--- a/docs/html/guide/topics/location/index.jd
+++ b/docs/html/guide/topics/location/index.jd
@@ -4,94 +4,63 @@
<div id="qv-wrapper">
<div id="qv">
- <h2>Location and Maps quickview</h2>
+ <h2>Quickview</h2>
<ul>
- <li>Android provides a location framework that your application can use to determine the device's location and bearing and register for updates.</li>
- <li>A Google Maps external library is available that lets you display and manage Maps data.</li>
+ <li>Android provides a location framework that your application can use to determine the
+device's location and bearing and register for updates</li>
+ <li>A Google Maps external library is available that lets you display and manage Maps data</li>
</ul>
- <h2>In this document</h2>
+
+ <h2>Topics</h2>
<ol>
- <li><a href="#location">Location Services</a></li>
- <li><a href="#maps">Google Maps External Library</a></li>
+ <li><a href="{@docRoot}guide/topics/location/obtaining-user-location.html">Obtaining User
+Location</a></li>
</ol>
+
<h2>See Also</h2>
<ol>
- <li><a href="http://code.google.com/android/add-ons/google-apis/index.html">Google APIs add-on download»</a></li>
+ <li><a
+href="http://code.google.com/android/add-ons/google-apis/maps-overview.html">Google
+Maps External Library »</a></li>
</ol>
</div>
</div>
-<p>Location- and maps-based applications and services are compelling for mobile device users. You can build these capabilities into your applications using the classes of the {@link android.location} package and the Google Maps external library. The sections below provide details. </p>
+<p>Location and maps-based applications are compelling for mobile device users. You
+can build these capabilities into your applications using the classes of the {@link
+android.location} package and the Google Maps external library. The sections below provide details.
+</p>
<h2 id="location">Location Services</h2>
<p>Android gives your applications access to the location services supported by
-the device through the classes in the <code>android.location</code> package. The
+the device through the classes in the {@code android.location} package. The
central component of the location framework is the
-{@link android.location.LocationManager} system service, which provides an API to
-determine location and bearing if the underlying device (if it supports location
-capabilities). </p>
+{@link android.location.LocationManager} system service, which provides APIs to
+determine location and bearing of the underlying device (if available). </p>
-<p>As with other system services, you do not instantiate a LocationManager directly.
-Rather, you request an LocationManager instance from the system by calling
-{@link android.content.Context#getSystemService(String) getSystemService(Context.LOCATION_SERVICE)}.
-The method returns a handle to a new LocationManager instance.</p>
+<p>As with other system services, you do not instantiate a {@link android.location.LocationManager}
+directly. Rather, you request an instance from the system by calling
+{@link android.content.Context#getSystemService(String)
+getSystemService(Context.LOCATION_SERVICE)}. The method returns a handle to a new {@link
+android.location.LocationManager} instance.</p>
-<p>Once your application has a handle to a LocationManager instance, your application
-will be able to do three things:</p>
+<p>Once your application has a {@link android.location.LocationManager}, your application
+is able to do three things:</p>
<ul>
- <li>Query for the list of all LocationProviders known to the
- LocationManager for its last known location.</li>
- <li>Register/unregister for periodic updates of current location from a
- LocationProvider (specified either by Criteria or name).</li>
- <li>Register/unregister for a given Intent to be fired if the device comes
- within a given proximity (specified by radius in meters) of a given
- lat/long.</li>
+ <li>Query for the list of all {@link android.location.LocationProvider}s for the last known
+user location.</li>
+ <li>Register/unregister for periodic updates of the user's current location from a
+ location provider (specified either by criteria or name).</li>
+ <li>Register/unregister for a given {@link android.content.Intent} to be fired if the device
+comes within a given proximity (specified by radius in meters) of a given lat/long.</li>
</ul>
-<p>However, during initial development in the emulator, you may not have access to real
-data from a real location provider (Network or GPS). In that case, it may be necessary to
-spoof some data for your application using a mock location provider.</p>
+<p>For more information, read the guide to <a
+href="{@docRoot}guide/topics/location/obtaining-user-location.html">Obtaining User
+Location</a>.</p>
-<p class="note"><strong>Note:</strong> If you've used mock LocationProviders in
-previous versions of the SDK, you can no longer provide canned LocationProviders
-in the /system/etc/location directory. These directories will be wiped during boot-up.
-Please follow the new procedures outlined below.</p>
-
-<h3>Providing Mock Location Data</h3>
-
-<p>When testing your application on the Android emulator, there are a couple different
-ways to send it some mock location data: you can use the DDMS tool or the "geo" command
-option in the emulator console.</p>
-
-<h4 id="ddms">Using DDMS</h4>
-<p>With the DDMS tool, you can simulate location data a few different ways:</p>
-<ul>
- <li>Manually send individual longitude/latitude coordinates to the device.</li>
- <li>Use a GPX file describing a route for playback to the device.</li>
- <li>Use a KML file describing individual placemarks for sequenced playback to the device.</li>
-</ul>
-<p>For more information on using DDMS to spoof location data, see the
-<a href="{@docRoot}guide/developing/tools/ddms.html#emulator-control">Using DDMS guide</a>.
-
-<h4 id="geo">Using the "geo" command in the emulator console</h4>
-<p>Launch your application in the Android emulator and open a terminal/console in
-your SDK's <code>/tools</code> directory. Connect to the emulator console. Now you can use:</p>
-<ul><li><code>geo fix</code> to send a fixed geo-location.
- <p>This command accepts a longitude and latitude in decimal degrees, and
- an optional altitude in meters. For example:</p>
- <pre>geo fix -121.45356 46.51119 4392</pre>
- </li>
- <li><code>geo nmea</code> to send an NMEA 0183 sentence.
- <p>This command accepts a single NMEA sentence of type '$GPGGA' (fix data) or '$GPRMC' (transit data).
- For example:</p>
- <pre>geo nmea $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62</pre>
- </li>
-</ul>
-
-<p>For information about how to connect to the emulator console, see
-<a href="{@docRoot}guide/developing/tools/emulator.html#console">Using the Emulator Console</a>.</p>
<h2 id="maps">Google Maps External Library</h2>
@@ -128,9 +97,9 @@
<p style="margin-left:2em;"><a
href="http://code.google.com/android/add-ons/google-apis">http://code.google.com/android/add-ons/google-apis</a></p>
-<p>For your convenience, the Google APIs add-on is also included in the Android
-SDK. <!-- To learn now to use the Maps external library in your application, see
-[[Using External Libraries]].--></p>
+<p>For your convenience, the Google APIs add-on is also available as a downloadable component from
+the Android SDK and AVD Manager (see <a href="{@docRoot}sdk/adding-components.html">Adding SDK
+Components</a>).</p>
<p class="note"><strong>Note:</strong> In order to display Google Maps data in a
MapView, you must register with the Google Maps service and obtain a Maps API
diff --git a/docs/html/guide/topics/location/obtaining-user-location.jd b/docs/html/guide/topics/location/obtaining-user-location.jd
new file mode 100644
index 0000000..bc782d2
--- /dev/null
+++ b/docs/html/guide/topics/location/obtaining-user-location.jd
@@ -0,0 +1,454 @@
+page.title=Obtaining User Location
+parent.title=Location and Maps
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+ <h2>Quickview</h2>
+ <ul>
+ <li>The Network Location Provider provides good location data without using GPS</li>
+ <li>Obtaining user location can consume a lot of battery, so be careful how
+long you listen for updates</li>
+ </ul>
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#Challenges">Challenges in Determining User Location</a></li>
+ <li><a href="#Updates">Requesting Location Updates</a>
+ <ol>
+ <li><a href="#Permission">Requesting User Permissions</a></li>
+ </ol>
+ </li>
+ <li><a href="#BestPerformance">Defining a Model for the Best Performance</a>
+ <ol>
+ <li><a href="#Flow">Flow for obtaining user location</a></li>
+ <li><a href="#StartListening">Deciding when to start listening for updates</a></li>
+ <li><a href="#FastFix">Getting a fast fix with the last known location</a></li>
+ <li><a href="#StopListening">Deciding when to stop listening for updates</a></li>
+ <li><a href="#BestEstimate">Maintaining a current best estimate</a></li>
+ <li><a href="#Adjusting">Adjusting the model to save battery and data exchange</a></li>
+ </ol>
+ </li>
+ <li><a href="#MockData">Providing Mock Location Data</a></li>
+ </ol>
+ <h2>Key classes</h2>
+ <ol>
+ <li>{@link android.location.LocationManager}</li>
+ <li>{@link android.location.LocationListener}</li>
+ </ol>
+</div>
+</div>
+
+ <p>Knowing where the user is allows your application to be smarter and deliver
+better information to the user. When developing a location-aware application for Android, you can
+utilize GPS and Android's Network Location Provider to acquire the user location. Although
+GPS is most accurate, it only works outdoors, it quickly consumes battery power, and doesn't return
+the location as quickly as users want. Android's Network Location Provider determines user location
+using cell tower and Wi-Fi signals, providing location information in a way that
+works indoors and outdoors, responds faster, and uses less battery power. To obtain the user
+location in your application, you can use both GPS and the Network Location Provider, or just
+one.</p>
+
+
+<h2 id="Challenges">Challenges in Determining User Location</h2>
+
+<p>Obtaining user location from a mobile device can be complicated. There are several reasons
+why a location reading (regardless of the source) can contain errors and be inaccurate.
+Some sources of error in the user location include:</p>
+
+<ul>
+ <li><b>Multitude of location sources</b>
+ <p>GPS, Cell-ID, and Wi-Fi can each provide a clue to users location. Determining which to use
+and trust is a matter of trade-offs in accuracy, speed, and battery-efficiency.</p>
+ </li>
+ <li><b>User movement</b>
+ <p>Because the user location changes, you must account for movement by re-estimating user
+location every so often.</p>
+ </li>
+ <li><b>Varying accuracy</b>
+ <p>Location estimates coming from each location source are not consistent in their
+accuracy. A location obtained 10 seconds ago from one source might be more accurate than the newest
+location from another or same source.</p>
+ </li>
+</ul>
+
+ <p>These problems can make it difficult to obtain a reliable user location reading. This
+document provides information to help you meet these challenges to obtain a reliable location
+reading. It also provides ideas that you can use in your
+application to provide the user with an accurate and responsive geo-location experience.</p>
+
+
+<h2 id="Updates">Requesting Location Updates</h2>
+
+ <p>Before addressing some of the location errors described above, here is an introduction to
+how you can obtain user location on Android.</p>
+
+ <p>Getting user location in Android works by means of callback. You indicate that you'd
+like to receive location updates from the {@link android.location.LocationManager} ("Location
+Manager") by calling {@link android.location.LocationManager#requestLocationUpdates
+requestLocationUpdates()}, passing it a
+{@link android.location.LocationListener}. Your {@link android.location.LocationListener} must
+implement several callback methods that the Location Manager calls when the user location
+changes or when the status of the service changes.</p>
+
+<p>For example, the following code shows how to define a {@link android.location.LocationListener}
+and request location updates:
+ </p>
+
+<pre>
+// Acquire a reference to the system Location Manager
+LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
+
+// Define a listener that responds to location updates
+LocationListener locationListener = new LocationListener() {
+ public void onLocationChanged(Location location) {
+ // Called when a new location is found by the network location provider.
+ makeUseOfNewLocation(location);
+ }
+
+ public void onStatusChanged(String provider, int status, Bundle extras) {}
+
+ public void onProviderEnabled(String provider) {}
+
+ public void onProviderDisabled(String provider) {}
+ };
+
+// Register the listener with the Location Manager to receive location updates
+locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
+</pre>
+
+ <p>The first parameter in {@link
+android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} is the type of
+location provider to use (in this case, the Network Location Provider for cell tower and Wi-Fi
+based location). You can control the frequency at which your listener receives updates
+with the second and third parameter—the second is the minimum time interval between
+notifications and the third is the minimum change in distance between notifications—setting
+both to zero requests location notifications as frequently as possible. The last parameter is your
+{@link android.location.LocationListener}, which receives callbacks for location updates.</p>
+
+<p>To request location updates from the GPS provider,
+substitute <code>GPS_PROVIDER</code> for <code>NETWORK_PROVIDER</code>. You can also request
+location updates from both the GPS and the Network Location Provider by calling {@link
+android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} twice—once
+for <code>NETWORK_PROVIDER</code> and once for <code>GPS_PROVIDER</code>.</p>
+
+
+<h3 id="Permission">Requesting User Permissions</h3>
+
+<p>In order to receive location updates from <code>NETWORK_PROVIDER</code> or
+<code>GPS_PROVIDER</code>, you must request user permission by declaring either the {@code
+ACCESS_COARSE_LOCATION} or {@code ACCESS_FINE_LOCATION} permission, respectively, in your Android
+manifest file. For example:</p>
+
+<pre>
+<manifest ... >
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ ...
+</manifest>
+</pre>
+
+<p>Without these permissions, your application will fail at runtime when requesting
+location updates.</p>
+
+<p class="note"><strong>Note:</strong> If you are using both <code>NETWORK_PROVIDER</code> and
+<code>GPS_PROVIDER</code>, then you need to request only the {@code ACCESS_FINE_LOCATION}
+permission, because it includes permission for both providers. (Permission for {@code
+ACCESS_COARSE_LOCATION} includes permission only for <code>NETWORK_PROVIDER</code>.)</p>
+
+
+<h2 id="BestPerformance">Defining a Model for the Best Performance</h2>
+
+ <p>Location-based applications are now commonplace, but due to the less than optimal
+accuracy, user movement, the multitude of methods to obtain the location, and the desire to conserve
+battery, getting user location is complicated. To overcome the obstacles of obtaining a good user
+location while preserving battery power, you must define a consistent model that specifies how your
+application obtains the user location. This model includes when you start and stop listening for
+updates and when to use cached location data.</p>
+
+
+ <h3 id="Flow">Flow for obtaining user location</h3>
+
+ <p>Here's the typical flow of procedures for obtaining the user location:</p>
+
+ <ol>
+ <li>Start application.</li>
+ <li>Sometime later, start listening for updates from desired location providers.</li>
+ <li>Maintain a "current best estimate" of location by filtering out new, but less accurate
+fixes.</li>
+ <li>Stop listening for location updates.</li>
+ <li>Take advantage of the last best location estimate.</li>
+ </ol>
+
+ <p>Figure 1 demonstrates this model in a timeline that visualizes the period in which an
+application is listening for location updates and the events that occur during that time.</p>
+
+<img src="{@docRoot}images/location/getting-location.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong> A timeline representing the window in which an
+application listens for location updates.</p>
+
+ <p>This model of a window—during which location updates are received—frames many of
+the decisions you need to make when adding location-based services to your application.</p>
+
+
+ <h3 id="StartListening">Deciding when to start listening for updates</h3>
+
+ <p>You might want to start listening for location updates as soon as your application starts, or
+only after users activate a certain feature. Be aware that long windows of listening for location
+fixes can consume a lot of battery power, but short periods might not allow for sufficient
+accuracy.</p>
+
+ <p>As demonstrated above, you can begin listening for updates by calling {@link
+android.location.LocationManager#requestLocationUpdates requestLocationUpdates()}:</p>
+
+<pre>
+LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER;
+// Or, use GPS location data:
+// LocationProvider locationProvider = LocationManager.GPS_PROVIDER;
+
+locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);
+</pre>
+
+
+ <h3 id="FastFix">Getting a fast fix with the last known location</h3>
+
+ <p>The time it takes for your location listener to receive the first location fix is often too
+long for users wait. Until a more accurate location is provided to your location listener, you
+should utilize a cached location by calling {@link
+android.location.LocationManager#getLastKnownLocation}:</p>
+<pre>
+LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER;
+// Or use LocationManager.GPS_PROVIDER
+
+Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
+</pre>
+
+
+ <h3 id="StopListening">Deciding when to stop listening for updates</h3>
+
+ <p>The logic of deciding when new fixes are no longer necessary might range from very simple to
+very complex depending on your application. A short gap between when the location is acquired and
+when the location is used, improves the accuracy of the estimate. Always beware that listening for a
+long time consumes a lot of battery power, so as soon as you have the information you need, you
+should stop
+listening for updates by calling {@link android.location.LocationManager#removeUpdates}:</p>
+<pre>
+// Remove the listener you previously added
+locationManager.removeUpdates(locationListener);
+</pre>
+
+
+ <h3 id="BestEstimate">Maintaining a current best estimate</h3>
+
+ <p>You might expect that the most recent location fix is the most accurate.
+However, because the accuracy of a location fix varies, the most recent fix is not always the best.
+You should include logic for choosing location fixes based on several criteria. The criteria also
+varies depending on the use-cases of the application and field testing.</p>
+
+ <p>Here are a few steps you can take to validate the accuracy of a location fix:</p>
+ <ul>
+ <li>Check if the location retrieved is significantly newer than the previous estimate.</li>
+ <li>Check if the accuracy claimed by the location is better or worse than the previous
+estimate.</li>
+ <li>Check which provider the new location is from and determine if you trust it more.</li>
+ </ul>
+
+ <p>An elaborate example of this logic can look something like this:</p>
+
+<pre>
+private static final int TWO_MINUTES = 1000 * 60 * 2;
+
+/** Determines whether one Location reading is better than the current Location fix
+ * @param location The new Location that you want to evaluate
+ * @param currentBestLocation The current Location fix, to which you want to compare the new one
+ */
+protected boolean isBetterLocation(Location location, Location currentBestLocation) {
+ if (currentBestLocation == null) {
+ // A new location is always better than no location
+ return true;
+ }
+
+ // Check whether the new location fix is newer or older
+ long timeDelta = location.getTime() - currentBestLocation.getTime();
+ boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
+ boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
+ boolean isNewer = timeDelta > 0;
+
+ // If it's been more than two minutes since the current location, use the new location
+ // because the user has likely moved
+ if (isSignificantlyNewer) {
+ return true;
+ // If the new location is more than two minutes older, it must be worse
+ } else if (isSignificantlyOlder) {
+ return false;
+ }
+
+ // Check whether the new location fix is more or less accurate
+ int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
+ boolean isLessAccurate = accuracyDelta > 0;
+ boolean isMoreAccurate = accuracyDelta < 0;
+ boolean isSignificantlyLessAccurate = accuracyDelta > 200;
+
+ // Check if the old and new location are from the same provider
+ boolean isFromSameProvider = isSameProvider(location.getProvider(),
+ currentBestLocation.getProvider());
+
+ // Determine location quality using a combination of timeliness and accuracy
+ if (isMoreAccurate) {
+ return true;
+ } else if (isNewer && !isLessAccurate) {
+ return true;
+ } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
+ return true;
+ }
+ return false;
+}
+
+/** Checks whether two providers are the same */
+private boolean isSameProvider(String provider1, String provider2) {
+ if (provider1 == null) {
+ return provider2 == null;
+ }
+ return provider1.equals(provider2);
+}
+</pre>
+
+
+ <h3 id="Adjusting">Adjusting the model to save battery and data exchange</h3>
+
+ <p>As you test your application, you might find that your model for providing good location and
+good performance needs some adjustment. Here are some things you might change to find a good
+balance between the two.</p>
+
+ <h4>Reduce the size of the window</h4>
+
+ <p>A smaller window in which you listen for location updates means less interaction with GPS and
+network location services, thus, preserving battery life. But it also allows for fewer locations
+from which to choose a best estimate.</p>
+
+ <h4>Set the location providers to return updates less frequently</h4>
+
+ <p>Reducing the rate at which new updates appear during the window can also improve battery
+efficiency, but at the cost of accuracy. The value of the trade-off depends on how your
+application is used. You can reduce the rate of updates by increasing the parameters in {@link
+android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} that specify the
+interval time and minimum distance change.</p>
+
+ <h4>Restrict a set of providers</h4>
+
+ <p>Depending on the environment where your application is used or the desired level of accuracy,
+you might choose to use only the Network Location Provider or only GPS, instead of both. Interacting
+with only one of the services reduces battery usage at a potential cost of accuracy.</p>
+
+
+ <h2>Common application cases</h2>
+
+ <p>There are many reasons you might want to obtain the user location in your application. Below
+are a couple scenarios in which you can use the user location to enrich your application. Each
+scenario also describes good practices for when you should start and stop listening for the
+location, in order to get a good reading and help preserve battery life.</p>
+
+
+ <h3>Tagging user-created content with a location</h3>
+
+ <p>You might be creating an application where user-created content is tagged with a location.
+Think of users sharing their local experiences, posting a review for a restaurant, or recording some
+content that can be augmented with their current location. A model of how this
+interaction might happen, with respect to the location services, is visualized in figure 2.</p>
+
+ <img src="{@docRoot}images/location/content-tagging.png" alt="" />
+<p class="img-caption"><strong>Figure 2.</strong> A timeline representing the window in which
+the user location is obtained and listening stops when the user consumes the current location.</p>
+
+ <p>This lines up with the previous model of how user location is obtained in code (figure 1). For
+best location accuracy, you might choose to start listening for location updates when users begin
+creating
+the content or even when the application starts, then stop listening for updates when content is
+ready to be posted or recorded. You might need to consider how long a typical task of creating the
+content takes and judge if this duration allows for efficient collection of a location estimate.</p>
+
+
+ <h3>Helping the user decide on where to go</h3>
+
+ <p>You might be creating an application that attempts to provide users with a set
+of options about where to go. For example, you're looking to provide a list of nearby restaurants,
+stores, and entertainment and the order of recommendations changes depending on the user
+location.</p>
+
+ <p>To accommodate such a flow, you might choose to:</p>
+ <ul>
+ <li>Rearrange recommendations when a new best estimate is obtained</li>
+ <li>Stop listening for updates if the order of recommendations has stabilized</li>
+ </ul>
+
+ <p>This kind of model is visualized in figure 3.</p>
+
+ <img src="{@docRoot}images/location/where-to-go.png" alt="" />
+<p class="img-caption"><strong>Figure 3.</strong> A timeline representing the window in which a
+dynamic set of data is updated each time the user location updates.</p>
+
+
+
+
+<h2 id="MockData">Providing Mock Location Data</h2>
+
+<p>As you develop your application, you'll certainly need to test how well your model for obtaining
+user location works. This is most easily done using a real Android-powered device. If, however, you
+don't have a device, you can still test your location-based features by mocking location data in
+the Android emulator. There are three different ways to send your application mock location
+data: using Eclipse, DDMS, or the "geo" command in the emulator console.</p>
+
+<p class="note"><strong>Note:</strong> Providing mock location data is injected as GPS location
+data, so you must request location updates from <code>GPS_PROVIDER</code> in order for mock location
+data to work.</p>
+
+<h3 id="MockEclipse">Using Eclipse</h3>
+
+<p>Select <b>Window</b> > <b>Show View</b> > <b>Other</b> > <b>Emulator Control</b>.</p>
+
+<p>In the Emulator Control panel, enter GPS coordinates under Location Controls as individual
+lat/long coordinates, with a GPX file for route playback, or a KML file for multiple place marks.
+(Be sure that you have a device selected in the Devices panel—available from <b>Window</b>
+> <b>Show View</b> > <b>Other</b> > <b>Devices</b>.)</p>
+
+
+<h3 id="MockDdms">Using DDMS</h3>
+
+<p>With the DDMS tool, you can simulate location data a few different ways:</p>
+<ul>
+ <li>Manually send individual longitude/latitude coordinates to the device.</li>
+ <li>Use a GPX file describing a route for playback to the device.</li>
+ <li>Use a KML file describing individual place marks for sequenced playback to the device.</li>
+</ul>
+
+<p>For more information on using DDMS to spoof location data, see the
+<a href="{@docRoot}guide/developing/tools/ddms.html#emulator-control">Using DDMS guide</a>.
+
+
+<h3 id="MockGeo">Using the "geo" command in the emulator console</h3>
+
+<p>To send mock location data from the command line:</p>
+
+<ol>
+ <li>Launch your application in the Android emulator and open a terminal/console in your SDK's
+<code>/tools</code> directory.</li>
+ <li>Connect to the emulator console:
+<pre>telnet localhost <em><console-port></em></pre></li>
+ <li>Send the location data:</p>
+ <ul><li><code>geo fix</code> to send a fixed geo-location.
+ <p>This command accepts a longitude and latitude in decimal degrees, and
+ an optional altitude in meters. For example:</p>
+ <pre>geo fix -121.45356 46.51119 4392</pre>
+ </li>
+ <li><code>geo nmea</code> to send an NMEA 0183 sentence.
+ <p>This command accepts a single NMEA sentence of type '$GPGGA' (fix data) or '$GPRMC' (transit
+ data).
+ For example:</p>
+ <pre>geo nmea $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62</pre>
+ </li>
+ </ul>
+ </li>
+</ol>
+
+<p>For information about how to connect to the emulator console, see
+<a href="{@docRoot}guide/developing/tools/emulator.html#console">Using the Emulator Console</a>.</p>
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index de8ca6d..e030a4c 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -336,10 +336,10 @@
</p></dd>
<dt><a name="lmode"></a>{@code android:launchMode}</dt>
-<dd>An instruction on how the activity should be launched. There are four modes
+<dd>An instruction on how the activity should be launched. There are four modes
that work in conjunction with activity flags ({@code FLAG_ACTIVITY_*} constants)
-in {@link android.content.Intent} objects to determine what should happen when
-the activity is called upon to handle an intent. They are:
+in {@link android.content.Intent} objects to determine what should happen when
+the activity is called upon to handle an intent. They are:</p>
<p style="margin-left: 2em">"{@code standard}"
<br>"{@code singleTop}"
@@ -351,56 +351,110 @@
</p>
<p>
-The modes fall into two main groups, with "{@code standard}" and
-"{@code singleTop}" activities on one side, and "{@code singleTask}" and
-"{@code singleInstance}" activities on the other. An activity with the
-"{@code standard}" or "{@code singleTop}" launch mode can be instantiated
-multiple times. The instances can belong to any task and can be located
-anywhere in the activity stack. Typically, they're launched into the task
-that called
+As shown in the table below, the modes fall into two main groups, with
+"{@code standard}" and "{@code singleTop}" activities on one side, and
+"{@code singleTask}" and "{@code singleInstance}" activities on the other.
+An activity with the "{@code standard}" or "{@code singleTop}" launch mode
+can be instantiated multiple times. The instances can belong to any task
+and can be located anywhere in the activity stack. Typically, they're
+launched into the task that called
<code>{@link android.content.Context#startActivity startActivity()}</code>
-(unless the Intent object contains a
-<code>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</code>
-instruction, in which case a different task is chosen — see the
+(unless the Intent object contains a
+<code>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</code>
+instruction, in which case a different task is chosen — see the
<a href="#aff">taskAffinity</a> attribute).
</p>
<p>
-In contrast, "{@code singleTask}" and "{@code singleInstance}" activities
-can only begin a task. They are always at the root of the activity stack.
-Moreover, the device can hold only one instance of the activity at a time
+In contrast, "<code>singleTask</code>" and "<code>singleInstance</code>" activities
+can only begin a task. They are always at the root of the activity stack.
+Moreover, the device can hold only one instance of the activity at a time
— only one such task.
</p>
<p>
The "{@code standard}" and "{@code singleTop}" modes differ from each other
-in just one respect: Every time there's new intent for a "{@code standard}"
-activity, a new instance of the class is created to respond to that intent.
+in just one respect: Every time there's a new intent for a "{@code standard}"
+activity, a new instance of the class is created to respond to that intent.
Each instance handles a single intent.
-Similarly, a new instance of a "{@code singleTop}" activity may also be
-created to handle a new intent. However, if the target task already has an
-existing instance of the activity at the top of its stack, that instance
-will receive the new intent (in an
+Similarly, a new instance of a "{@code singleTop}" activity may also be
+created to handle a new intent. However, if the target task already has an
+existing instance of the activity at the top of its stack, that instance
+will receive the new intent (in an
<code>{@link android.app.Activity#onNewIntent onNewIntent()}</code> call);
a new instance is not created.
-In other circumstances — for example, if an existing instance of the
-"{@code singleTop}" activity is in the target task, but not at the top of
-the stack, or if it's at the top of a stack, but not in the target task
+In other circumstances — for example, if an existing instance of the
+"{@code singleTop}" activity is in the target task, but not at the top of
+the stack, or if it's at the top of a stack, but not in the target task
— a new instance would be created and pushed on the stack.
-</p>
+</p>
<p>
-The "{@code singleTask}" and "{@code singleInstance}" modes also differ from
-each other in only one respect: A "{@code singleTask}" activity allows other
-activities to be part of its task. It's at the root of the activity stack,
-but other activities (necessarily "{@code standard}" and "{@code singleTop}"
-activities) can be launched into the same task. A "{@code singleInstance}"
-activity, on the other hand, permits no other activities to be part of its
-task. It's the only activity in the task. If it starts another activity,
-that activity is assigned to a different task — as if {@code
+The "{@code singleTask}" and "{@code singleInstance}" modes also differ from
+each other in only one respect: A "{@code singleTask}" activity allows other
+activities to be part of its task. It's always at the root of its task, but
+other activities (necessarily "{@code standard}" and "{@code singleTop}"
+activities) can be launched into that task. A "{@code singleInstance}"
+activity, on the other hand, permits no other activities to be part of its task.
+It's the only activity in the task. If it starts another activity, that
+activity is assigned to a different task — as if {@code
FLAG_ACTIVITY_NEW_TASK} was in the intent.
</p>
+<table>
+<tr>
+<th>Use Cases</th>
+<th>Launch Mode</th>
+<th>Multiple Instances?</th>
+<th>Comments</th>
+</tr>
+<tr>
+<td rowspan="2" style="width:20%;">Normal launches for most activities</td>
+<td>"<code>standard</code>"</td>
+<td>Yes</td>
+<td>Default. The system always creates a new instance of the activity in the
+target task and routes the intent to it.</td>
+</tr>
+<tr>
+<td>"<code>singleTop</code>"</td>
+<td>Conditionally</td>
+<td>If an instance of the activity already exists at the top of the target task,
+the system routes the intent to that instance through a call to its {@link
+android.app.Activity#onNewIntent onNewIntent()} method, rather than creating a
+new instance of the activity.</td>
+</tr>
+<tr>
+<td rowspan="2">Specialized launches<br>
+<em>(not recommended for general use)</em></td>
+<td>"<code>singleTask</code>"</td>
+<td>No</td>
+<td>The system creates the activity at the root of a new task and routes the
+intent to it. However, if an instance of the activity already exists, the system
+routes the intent to existing instance through a call to its {@link
+android.app.Activity#onNewIntent onNewIntent()} method, rather than creating a
+new one.</td>
+</tr>
+<tr>
+<td>"<code>singleInstance</code>"</td>
+<td>No</td>
+<td>Same as "<code>singleTask"</code>, except that the system doesn't launch any
+other activities into the task holding the instance. The activity is always the
+single and only member of its task.</td>
+</tr>
+</table>
+
+<p>As shown in the table above, <code>standard</code> is the default mode and is
+appropriate for most types of activities. <code>SingleTop</code> is also a
+common and useful launch mode for many types of activities. The other modes
+— <code>singleTask</code> and <code>singleInstance</code> — are
+<span style="color:red">not appropriate for most applications</span>,
+since they result in an interaction model that is likely to be unfamiliar to
+users and is very different from most other applications.
+
+<p>Regardless of the launch mode that you choose, make sure to test the usability
+of the activity during launch and when navigating back to it from
+other activities and tasks using the BACK key. </p>
+
<p>For more information on launch modes and their interaction with Intent
flags, see the
<a href="{@docRoot}guide/topics/fundamentals.html#acttask">Activities and
diff --git a/docs/html/images/location/content-tagging.png b/docs/html/images/location/content-tagging.png
new file mode 100644
index 0000000..d58bfee
--- /dev/null
+++ b/docs/html/images/location/content-tagging.png
Binary files differ
diff --git a/docs/html/images/location/getting-location.png b/docs/html/images/location/getting-location.png
new file mode 100644
index 0000000..a5905ec
--- /dev/null
+++ b/docs/html/images/location/getting-location.png
Binary files differ
diff --git a/docs/html/images/location/where-to-go.png b/docs/html/images/location/where-to-go.png
new file mode 100644
index 0000000..59f5983
--- /dev/null
+++ b/docs/html/images/location/where-to-go.png
Binary files differ
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index f1f673b..6775c08 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -395,6 +395,17 @@
static public Allocation createFromBitmapResourceBoxed(RenderScript rs, Resources res, int id, Element dstFmt, boolean genMips)
throws IllegalArgumentException {
+ mBitmapOptions.inPreferredConfig = null;
+ if (dstFmt == rs.mElement_RGBA_8888) {
+ mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ } else if (dstFmt == rs.mElement_RGB_888) {
+ mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ } else if (dstFmt == rs.mElement_RGBA_4444) {
+ mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_4444;
+ } else if (dstFmt == rs.mElement_RGB_565) {
+ mBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
+ }
+
Bitmap b = BitmapFactory.decodeResource(res, id, mBitmapOptions);
return createFromBitmapBoxed(rs, b, dstFmt, genMips);
}
diff --git a/graphics/java/android/renderscript/ProgramRaster.java b/graphics/java/android/renderscript/ProgramRaster.java
index 08065cf..fd89b6e 100644
--- a/graphics/java/android/renderscript/ProgramRaster.java
+++ b/graphics/java/android/renderscript/ProgramRaster.java
@@ -67,17 +67,46 @@
mRS.nProgramRasterSetCullMode(mID, m.mID);
}
+ public static ProgramRaster CULL_BACK(RenderScript rs) {
+ if(rs.mProgramRaster_CULL_BACK == null) {
+ ProgramRaster.Builder builder = new ProgramRaster.Builder(rs);
+ builder.setCullMode(CullMode.BACK);
+ rs.mProgramRaster_CULL_BACK = builder.create();
+ }
+ return rs.mProgramRaster_CULL_BACK;
+ }
+
+ public static ProgramRaster CULL_FRONT(RenderScript rs) {
+ if(rs.mProgramRaster_CULL_FRONT == null) {
+ ProgramRaster.Builder builder = new ProgramRaster.Builder(rs);
+ builder.setCullMode(CullMode.FRONT);
+ rs.mProgramRaster_CULL_FRONT = builder.create();
+ }
+ return rs.mProgramRaster_CULL_FRONT;
+ }
+
+ public static ProgramRaster CULL_NONE(RenderScript rs) {
+ if(rs.mProgramRaster_CULL_NONE == null) {
+ ProgramRaster.Builder builder = new ProgramRaster.Builder(rs);
+ builder.setCullMode(CullMode.NONE);
+ rs.mProgramRaster_CULL_NONE = builder.create();
+ }
+ return rs.mProgramRaster_CULL_NONE;
+ }
+
public static class Builder {
RenderScript mRS;
boolean mPointSprite;
boolean mPointSmooth;
boolean mLineSmooth;
+ CullMode mCullMode;
public Builder(RenderScript rs) {
mRS = rs;
mPointSmooth = false;
mLineSmooth = false;
mPointSprite = false;
+ mCullMode = CullMode.BACK;
}
public Builder setPointSpriteEnable(boolean enable) {
@@ -95,9 +124,15 @@
return this;
}
+ public Builder setCullMode(CullMode m) {
+ mCullMode = m;
+ return this;
+ }
+
static synchronized ProgramRaster internalCreate(RenderScript rs, Builder b) {
int id = rs.nProgramRasterCreate(b.mPointSmooth, b.mLineSmooth, b.mPointSprite);
ProgramRaster pr = new ProgramRaster(id, rs);
+ pr.setCullMode(b.mCullMode);
return pr;
}
diff --git a/graphics/java/android/renderscript/ProgramStore.java b/graphics/java/android/renderscript/ProgramStore.java
index e249842..32c0d01 100644
--- a/graphics/java/android/renderscript/ProgramStore.java
+++ b/graphics/java/android/renderscript/ProgramStore.java
@@ -79,139 +79,139 @@
super(id, rs);
}
- public static ProgramStore BlendNone_DepthTest(RenderScript rs) {
- if(rs.mProgramStore_BlendNone_DepthTest == null) {
+ public static ProgramStore BLEND_NONE_DEPTH_TEST(RenderScript rs) {
+ if(rs.mProgramStore_BLEND_NONE_DEPTH_TEST == null) {
ProgramStore.Builder builder = new ProgramStore.Builder(rs);
builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
builder.setDitherEnable(false);
builder.setDepthMask(true);
- rs.mProgramStore_BlendNone_DepthTest = builder.create();
+ rs.mProgramStore_BLEND_NONE_DEPTH_TEST = builder.create();
}
- return rs.mProgramStore_BlendNone_DepthTest;
+ return rs.mProgramStore_BLEND_NONE_DEPTH_TEST;
}
- public static ProgramStore BlendNone_DepthNoDepth(RenderScript rs) {
- if(rs.mProgramStore_BlendNone_DepthNoDepth == null) {
+ public static ProgramStore BLEND_NONE_DEPTH_NO_DEPTH(RenderScript rs) {
+ if(rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH == null) {
ProgramStore.Builder builder = new ProgramStore.Builder(rs);
builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
builder.setDitherEnable(false);
builder.setDepthMask(false);
- rs.mProgramStore_BlendNone_DepthNoDepth = builder.create();
+ rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH = builder.create();
}
- return rs.mProgramStore_BlendNone_DepthNoDepth;
+ return rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH;
}
- public static ProgramStore BlendNone_DepthNoTest(RenderScript rs) {
- if(rs.mProgramStore_BlendNone_DepthNoTest == null) {
+ public static ProgramStore BLEND_NONE_DEPTH_NO_TEST(RenderScript rs) {
+ if(rs.mProgramStore_BLEND_NONE_DEPTH_NO_TEST == null) {
ProgramStore.Builder builder = new ProgramStore.Builder(rs);
builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
builder.setDitherEnable(false);
builder.setDepthMask(true);
- rs.mProgramStore_BlendNone_DepthNoTest = builder.create();
+ rs.mProgramStore_BLEND_NONE_DEPTH_NO_TEST = builder.create();
}
- return rs.mProgramStore_BlendNone_DepthNoTest;
+ return rs.mProgramStore_BLEND_NONE_DEPTH_NO_TEST;
}
- public static ProgramStore BlendNone_DepthNoWrite(RenderScript rs) {
- if(rs.mProgramStore_BlendNone_DepthNoWrite == null) {
+ public static ProgramStore BLEND_NONE_DEPTH_NO_WRITE(RenderScript rs) {
+ if(rs.mProgramStore_BLEND_NONE_DEPTH_NO_WRITE == null) {
ProgramStore.Builder builder = new ProgramStore.Builder(rs);
builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
builder.setDitherEnable(false);
builder.setDepthMask(false);
- rs.mProgramStore_BlendNone_DepthNoWrite = builder.create();
+ rs.mProgramStore_BLEND_NONE_DEPTH_NO_WRITE = builder.create();
}
- return rs.mProgramStore_BlendNone_DepthNoWrite;
+ return rs.mProgramStore_BLEND_NONE_DEPTH_NO_WRITE;
}
- public static ProgramStore BlendAlpha_DepthTest(RenderScript rs) {
- if(rs.mProgramStore_BlendAlpha_DepthTest == null) {
+ public static ProgramStore BLEND_ALPHA_DEPTH_TEST(RenderScript rs) {
+ if(rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST == null) {
ProgramStore.Builder builder = new ProgramStore.Builder(rs);
builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
builder.setDitherEnable(false);
builder.setDepthMask(true);
- rs.mProgramStore_BlendAlpha_DepthTest = builder.create();
+ rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST = builder.create();
}
- return rs.mProgramStore_BlendAlpha_DepthTest;
+ return rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST;
}
- public static ProgramStore BlendAlpha_DepthNoDepth(RenderScript rs) {
- if(rs.mProgramStore_BlendAlpha_DepthNoDepth == null) {
+ public static ProgramStore BLEND_ALPHA_DEPTH_NO_DEPTH(RenderScript rs) {
+ if(rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH == null) {
ProgramStore.Builder builder = new ProgramStore.Builder(rs);
builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
builder.setDitherEnable(false);
builder.setDepthMask(false);
- rs.mProgramStore_BlendAlpha_DepthNoDepth = builder.create();
+ rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH = builder.create();
}
- return rs.mProgramStore_BlendAlpha_DepthNoDepth;
+ return rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH;
}
- public static ProgramStore BlendAlpha_DepthNoTest(RenderScript rs) {
- if(rs.mProgramStore_BlendAlpha_DepthNoTest == null) {
+ public static ProgramStore BLEND_ALPHA_DEPTH_NO_TEST(RenderScript rs) {
+ if(rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_TEST == null) {
ProgramStore.Builder builder = new ProgramStore.Builder(rs);
builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
builder.setDitherEnable(false);
builder.setDepthMask(true);
- rs.mProgramStore_BlendAlpha_DepthNoTest = builder.create();
+ rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_TEST = builder.create();
}
- return rs.mProgramStore_BlendAlpha_DepthNoTest;
+ return rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_TEST;
}
- public static ProgramStore BlendAlpha_DepthNoWrite(RenderScript rs) {
- if(rs.mProgramStore_BlendAlpha_DepthNoWrite == null) {
+ public static ProgramStore BLEND_ALPHA_DEPTH_NO_WRITE(RenderScript rs) {
+ if(rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_WRITE == null) {
ProgramStore.Builder builder = new ProgramStore.Builder(rs);
builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
builder.setDitherEnable(false);
builder.setDepthMask(false);
- rs.mProgramStore_BlendAlpha_DepthNoWrite = builder.create();
+ rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_WRITE = builder.create();
}
- return rs.mProgramStore_BlendAlpha_DepthNoWrite;
+ return rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_WRITE;
}
- public static ProgramStore BlendAdd_DepthTest(RenderScript rs) {
- if(rs.mProgramStore_BlendAdd_DepthTest == null) {
+ public static ProgramStore BLEND_ADD_DEPTH_TEST(RenderScript rs) {
+ if(rs.mProgramStore_BLEND_ADD_DEPTH_TEST == null) {
ProgramStore.Builder builder = new ProgramStore.Builder(rs);
builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
builder.setDitherEnable(false);
builder.setDepthMask(true);
- rs.mProgramStore_BlendAdd_DepthTest = builder.create();
+ rs.mProgramStore_BLEND_ADD_DEPTH_TEST = builder.create();
}
- return rs.mProgramStore_BlendAdd_DepthTest;
+ return rs.mProgramStore_BLEND_ADD_DEPTH_TEST;
}
- public static ProgramStore BlendAdd_DepthNoDepth(RenderScript rs) {
- if(rs.mProgramStore_BlendAdd_DepthNoDepth == null) {
+ public static ProgramStore BLEND_ADD_DEPTH_NO_DEPTH(RenderScript rs) {
+ if(rs.mProgramStore_BLEND_ADD_DEPTH_NO_DEPTH == null) {
ProgramStore.Builder builder = new ProgramStore.Builder(rs);
builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
builder.setDitherEnable(false);
builder.setDepthMask(false);
- rs.mProgramStore_BlendAdd_DepthNoDepth = builder.create();
+ rs.mProgramStore_BLEND_ADD_DEPTH_NO_DEPTH = builder.create();
}
- return rs.mProgramStore_BlendAdd_DepthNoDepth;
+ return rs.mProgramStore_BLEND_ADD_DEPTH_NO_DEPTH;
}
- public static ProgramStore BlendAdd_DepthNoTest(RenderScript rs) {
- if(rs.mProgramStore_BlendAdd_DepthNoTest == null) {
+ public static ProgramStore BLEND_ADD_DEPTH_NO_TEST(RenderScript rs) {
+ if(rs.mProgramStore_BLEND_ADD_DEPTH_NO_TEST == null) {
ProgramStore.Builder builder = new ProgramStore.Builder(rs);
builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
builder.setDitherEnable(false);
builder.setDepthMask(true);
- rs.mProgramStore_BlendAdd_DepthNoDepth = builder.create();
+ rs.mProgramStore_BLEND_ADD_DEPTH_NO_DEPTH = builder.create();
}
- return rs.mProgramStore_BlendAdd_DepthNoTest;
+ return rs.mProgramStore_BLEND_ADD_DEPTH_NO_TEST;
}
- public static ProgramStore BlendAdd_DepthNoWrite(RenderScript rs) {
- if(rs.mProgramStore_BlendAdd_DepthNoWrite == null) {
+ public static ProgramStore BLEND_ADD_DEPTH_NO_WRITE(RenderScript rs) {
+ if(rs.mProgramStore_BLEND_ADD_DEPTH_NO_WRITE == null) {
ProgramStore.Builder builder = new ProgramStore.Builder(rs);
builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
builder.setDitherEnable(false);
builder.setDepthMask(false);
- rs.mProgramStore_BlendAdd_DepthNoWrite = builder.create();
+ rs.mProgramStore_BLEND_ADD_DEPTH_NO_WRITE = builder.create();
}
- return rs.mProgramStore_BlendAdd_DepthNoWrite;
+ return rs.mProgramStore_BLEND_ADD_DEPTH_NO_WRITE;
}
public static class Builder {
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 37c01f5..ab1d7650 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -549,19 +549,22 @@
Sampler mSampler_WRAP_LINEAR;
Sampler mSampler_WRAP_LINEAR_MIP_LINEAR;
- ProgramStore mProgramStore_BlendNone_DepthTest;
- ProgramStore mProgramStore_BlendNone_DepthNoDepth;
- ProgramStore mProgramStore_BlendNone_DepthNoTest;
- ProgramStore mProgramStore_BlendNone_DepthNoWrite;
- ProgramStore mProgramStore_BlendAlpha_DepthTest;
- ProgramStore mProgramStore_BlendAlpha_DepthNoDepth;
- ProgramStore mProgramStore_BlendAlpha_DepthNoTest;
- ProgramStore mProgramStore_BlendAlpha_DepthNoWrite;
- ProgramStore mProgramStore_BlendAdd_DepthTest;
- ProgramStore mProgramStore_BlendAdd_DepthNoDepth;
- ProgramStore mProgramStore_BlendAdd_DepthNoTest;
- ProgramStore mProgramStore_BlendAdd_DepthNoWrite;
+ ProgramStore mProgramStore_BLEND_NONE_DEPTH_TEST;
+ ProgramStore mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH;
+ ProgramStore mProgramStore_BLEND_NONE_DEPTH_NO_TEST;
+ ProgramStore mProgramStore_BLEND_NONE_DEPTH_NO_WRITE;
+ ProgramStore mProgramStore_BLEND_ALPHA_DEPTH_TEST;
+ ProgramStore mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH;
+ ProgramStore mProgramStore_BLEND_ALPHA_DEPTH_NO_TEST;
+ ProgramStore mProgramStore_BLEND_ALPHA_DEPTH_NO_WRITE;
+ ProgramStore mProgramStore_BLEND_ADD_DEPTH_TEST;
+ ProgramStore mProgramStore_BLEND_ADD_DEPTH_NO_DEPTH;
+ ProgramStore mProgramStore_BLEND_ADD_DEPTH_NO_TEST;
+ ProgramStore mProgramStore_BLEND_ADD_DEPTH_NO_WRITE;
+ ProgramRaster mProgramRaster_CULL_BACK;
+ ProgramRaster mProgramRaster_CULL_FRONT;
+ ProgramRaster mProgramRaster_CULL_NONE;
///////////////////////////////////////////////////////////////////////////////////
//
diff --git a/graphics/java/android/renderscript/Sampler.java b/graphics/java/android/renderscript/Sampler.java
index ccd46bd..343fcdb 100644
--- a/graphics/java/android/renderscript/Sampler.java
+++ b/graphics/java/android/renderscript/Sampler.java
@@ -78,7 +78,7 @@
if(rs.mSampler_CLAMP_LINEAR_MIP_LINEAR == null) {
Builder b = new Builder(rs);
b.setMin(Value.LINEAR_MIP_LINEAR);
- b.setMag(Value.LINEAR_MIP_LINEAR);
+ b.setMag(Value.LINEAR);
b.setWrapS(Value.CLAMP);
b.setWrapT(Value.CLAMP);
rs.mSampler_CLAMP_LINEAR_MIP_LINEAR = b.create();
@@ -114,7 +114,7 @@
if(rs.mSampler_WRAP_LINEAR_MIP_LINEAR == null) {
Builder b = new Builder(rs);
b.setMin(Value.LINEAR_MIP_LINEAR);
- b.setMag(Value.LINEAR_MIP_LINEAR);
+ b.setMag(Value.LINEAR);
b.setWrapS(Value.WRAP);
b.setWrapT(Value.WRAP);
rs.mSampler_WRAP_LINEAR_MIP_LINEAR = b.create();
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 964700b..75cf5ff 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -22,8 +22,6 @@
namespace android {
-class ISurface;
-
/*
* A set of bit masks for specifying how the received preview frames are
* handled before the previewCallback() call.
@@ -152,9 +150,8 @@
status_t getStatus() { return mStatus; }
- // pass the buffered ISurface to the camera service
+ // pass the buffered Surface to the camera service
status_t setPreviewDisplay(const sp<Surface>& surface);
- status_t setPreviewDisplay(const sp<ISurface>& surface);
// start preview mode, must call setPreviewDisplay first
status_t startPreview();
diff --git a/include/camera/CameraHardwareInterface.h b/include/camera/CameraHardwareInterface.h
index 1529db7..515d879 100644
--- a/include/camera/CameraHardwareInterface.h
+++ b/include/camera/CameraHardwareInterface.h
@@ -18,6 +18,7 @@
#define ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H
#include <binder/IMemory.h>
+#include <ui/egl/android_natives.h>
#include <utils/RefBase.h>
#include <surfaceflinger/ISurface.h>
#include <camera/Camera.h>
@@ -86,8 +87,8 @@
public:
virtual ~CameraHardwareInterface() { }
- /** Return the IMemoryHeap for the preview image heap */
- virtual sp<IMemoryHeap> getPreviewHeap() const = 0;
+ /** Set the ISurface from which the preview buffers should be dequeued */
+ virtual status_t setPreviewWindow(const sp<ANativeWindow>& buf) = 0;
/** Return the IMemoryHeap for the raw image heap */
virtual sp<IMemoryHeap> getRawHeap() const = 0;
@@ -221,6 +222,7 @@
*/
extern "C" int HAL_getNumberOfCameras();
extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo);
+/* HAL should return NULL if it fails to open camera hardware. */
extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId);
}; // namespace android
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 4bc1799..a5c7874 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -61,6 +61,7 @@
void getSupportedPreviewSizes(Vector<Size> &sizes) const;
void setPreviewFrameRate(int fps);
int getPreviewFrameRate() const;
+ void getPreviewFpsRange(int *min_fps, int *max_fps) const;
void setPreviewFormat(const char *format);
const char *getPreviewFormat() const;
void setPictureSize(int width, int height);
@@ -82,6 +83,20 @@
// Supported preview frame sizes in pixels.
// Example value: "800x600,480x320". Read only.
static const char KEY_SUPPORTED_PREVIEW_SIZES[];
+ // The current minimum and maximum preview fps. This controls the rate of
+ // preview frames received (CAMERA_MSG_PREVIEW_FRAME). The minimum and
+ // maximum fps must be one of the elements from
+ // KEY_SUPPORTED_PREVIEW_FPS_RANGE parameter.
+ // Example value: "10500,26623"
+ static const char KEY_PREVIEW_FPS_RANGE[];
+ // The supported preview fps (frame-per-second) ranges. Each range contains
+ // a minimum fps and maximum fps. If minimum fps equals to maximum fps, the
+ // camera outputs frames in fixed frame rate. If not, the camera outputs
+ // frames in auto frame rate. The actual frame rate fluctuates between the
+ // minimum and the maximum. The list has at least one element. The list is
+ // sorted from small to large (first by maximum fps and then minimum fps).
+ // Example value: "(10500,26623),(15000,26623),(30000,30000)"
+ static const char KEY_SUPPORTED_PREVIEW_FPS_RANGE[];
// The image format for preview frames. See CAMERA_MSG_PREVIEW_FRAME in
// frameworks/base/include/camera/Camera.h.
// Example value: "yuv420sp" or PIXEL_FORMAT_XXX constants. Read/write.
diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h
index 6fcf9e5..8bceea5 100644
--- a/include/camera/ICamera.h
+++ b/include/camera/ICamera.h
@@ -20,7 +20,7 @@
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
-#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/Surface.h>
#include <binder/IMemory.h>
#include <utils/String8.h>
#include <camera/Camera.h>
@@ -45,8 +45,8 @@
// allow other processes to use this ICamera interface
virtual status_t unlock() = 0;
- // pass the buffered ISurface to the camera service
- virtual status_t setPreviewDisplay(const sp<ISurface>& surface) = 0;
+ // pass the buffered Surface to the camera service
+ virtual status_t setPreviewDisplay(const sp<Surface>& surface) = 0;
// set the preview callback flag to affect how the received frames from
// preview are handled.
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index af9a7ed..a1ce113 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -25,6 +25,7 @@
class Parcel;
class ISurface;
+class Surface;
class IMediaPlayer: public IInterface
{
@@ -33,7 +34,8 @@
virtual void disconnect() = 0;
- virtual status_t setVideoSurface(const sp<ISurface>& surface) = 0;
+ virtual status_t setVideoISurface(const sp<ISurface>& surface) = 0;
+ virtual status_t setVideoSurface(const sp<Surface>& surface) = 0;
virtual status_t prepareAsync() = 0;
virtual status_t start() = 0;
virtual status_t stop() = 0;
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 54adca8..54b197c 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -22,7 +22,7 @@
namespace android {
-class ISurface;
+class Surface;
class ICamera;
class IMediaRecorderClient;
@@ -32,7 +32,7 @@
DECLARE_META_INTERFACE(MediaRecorder);
virtual status_t setCamera(const sp<ICamera>& camera) = 0;
- virtual status_t setPreviewSurface(const sp<ISurface>& surface) = 0;
+ virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
virtual status_t setVideoSource(int vs) = 0;
virtual status_t setAudioSource(int as) = 0;
virtual status_t setOutputFormat(int of) = 0;
@@ -68,4 +68,3 @@
}; // namespace android
#endif // ANDROID_IMEDIARECORDER_H
-
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 3662983..13c73ac 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -33,6 +33,7 @@
class Parcel;
class ISurface;
+class Surface;
template<typename T> class SortedVector;
@@ -104,7 +105,8 @@
const KeyedVector<String8, String8> *headers = NULL) = 0;
virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
- virtual status_t setVideoSurface(const sp<ISurface>& surface) = 0;
+ virtual status_t setVideoISurface(const sp<ISurface>& surface) = 0;
+ virtual status_t setVideoSurface(const sp<Surface>& surface) = 0;
virtual status_t prepare() = 0;
virtual status_t prepareAsync() = 0;
virtual status_t start() = 0;
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 5e9e368..e5edd29 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -22,7 +22,7 @@
namespace android {
-class ISurface;
+class Surface;
struct MediaRecorderBase {
MediaRecorderBase() {}
@@ -37,7 +37,7 @@
virtual status_t setVideoSize(int width, int height) = 0;
virtual status_t setVideoFrameRate(int frames_per_second) = 0;
virtual status_t setCamera(const sp<ICamera>& camera) = 0;
- virtual status_t setPreviewSurface(const sp<ISurface>& surface) = 0;
+ virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
virtual status_t setOutputFile(const char *path) = 0;
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
virtual status_t setParameters(const String8& params) = 0;
diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h
index c091c39..4b44ccc 100644
--- a/include/media/PVMediaRecorder.h
+++ b/include/media/PVMediaRecorder.h
@@ -23,7 +23,7 @@
namespace android {
-class ISurface;
+class Surface;
class ICamera;
class AuthorDriverWrapper;
@@ -41,7 +41,7 @@
virtual status_t setVideoSize(int width, int height);
virtual status_t setVideoFrameRate(int frames_per_second);
virtual status_t setCamera(const sp<ICamera>& camera);
- virtual status_t setPreviewSurface(const sp<ISurface>& surface);
+ virtual status_t setPreviewSurface(const sp<Surface>& surface);
virtual status_t setOutputFile(const char *path);
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
virtual status_t setParameters(const String8& params);
@@ -66,4 +66,3 @@
}; // namespace android
#endif // ANDROID_PVMEDIARECORDER_H
-
diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h
index df50981..657e7a6 100644
--- a/include/media/PVPlayer.h
+++ b/include/media/PVPlayer.h
@@ -43,7 +43,8 @@
const char *url, const KeyedVector<String8, String8> *headers);
virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- virtual status_t setVideoSurface(const sp<ISurface>& surface);
+ virtual status_t setVideoISurface(const sp<ISurface>& surface);
+ virtual status_t setVideoSurface(const sp<Surface>& surface);
virtual status_t prepare();
virtual status_t prepareAsync();
virtual status_t start();
diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h
index 5d51de8..b8746c2 100644
--- a/include/media/Visualizer.h
+++ b/include/media/Visualizer.h
@@ -151,7 +151,6 @@
void *mCaptureCbkUser;
sp<CaptureThread> mCaptureThread;
uint32_t mCaptureFlags;
- void *mFftTable;
};
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index de82b38..2412f6a 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -40,6 +40,7 @@
virtual status_t stop();
virtual status_t pause();
virtual bool reachedEOS();
+ virtual status_t dump(int fd, const Vector<String16>& args);
void beginBox(const char *fourcc);
void writeInt8(int8_t x);
diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h
index 151bf16..5cc8dcf 100644
--- a/include/media/stagefright/MediaWriter.h
+++ b/include/media/stagefright/MediaWriter.h
@@ -44,6 +44,10 @@
mListener = listener;
}
+ virtual status_t dump(int fd, const Vector<String16>& args) {
+ return OK;
+ }
+
protected:
virtual ~MediaWriter() {}
int64_t mMaxFileSizeLimitBytes;
diff --git a/include/storage/IMountService.h b/include/storage/IMountService.h
new file mode 100644
index 0000000..a2735a4
--- /dev/null
+++ b/include/storage/IMountService.h
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_IMOUNTSERVICE_H
+#define ANDROID_IMOUNTSERVICE_H
+
+#include <storage/IMountServiceListener.h>
+#include <storage/IMountShutdownObserver.h>
+#include <storage/IObbActionListener.h>
+
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class IMountService: public IInterface {
+public:
+ DECLARE_META_INTERFACE(MountService);
+
+ virtual void registerListener(const sp<IMountServiceListener>& listener) = 0;
+ virtual void
+ unregisterListener(const sp<IMountServiceListener>& listener) = 0;
+ virtual bool isUsbMassStorageConnected() = 0;
+ virtual void setUsbMassStorageEnabled(const bool enable) = 0;
+ virtual bool isUsbMassStorageEnabled() = 0;
+ virtual int32_t mountVolume(const String16& mountPoint) = 0;
+ virtual int32_t
+ unmountVolume(const String16& mountPoint, const bool force) = 0;
+ virtual int32_t formatVolume(const String16& mountPoint) = 0;
+ virtual int32_t
+ getStorageUsers(const String16& mountPoint, int32_t** users) = 0;
+ virtual int32_t getVolumeState(const String16& mountPoint) = 0;
+ virtual int32_t createSecureContainer(const String16& id,
+ const int32_t sizeMb, const String16& fstype, const String16& key,
+ const int32_t ownerUid) = 0;
+ virtual int32_t finalizeSecureContainer(const String16& id) = 0;
+ virtual int32_t destroySecureContainer(const String16& id) = 0;
+ virtual int32_t mountSecureContainer(const String16& id,
+ const String16& key, const int32_t ownerUid) = 0;
+ virtual int32_t
+ unmountSecureContainer(const String16& id, const bool force) = 0;
+ virtual bool isSecureContainerMounted(const String16& id) = 0;
+ virtual int32_t renameSecureContainer(const String16& oldId,
+ const String16& newId) = 0;
+ virtual bool getSecureContainerPath(const String16& id, String16& path) = 0;
+ virtual int32_t getSecureContainerList(const String16& id,
+ String16*& containers) = 0;
+ virtual void shutdown(const sp<IMountShutdownObserver>& observer) = 0;
+ virtual void finishMediaUpdate() = 0;
+ virtual void mountObb(const String16& filename, const String16& key,
+ const sp<IObbActionListener>& token) = 0;
+ virtual void unmountObb(const String16& filename, const bool force) = 0;
+ virtual bool isObbMounted(const String16& filename) = 0;
+ virtual bool getMountedObbPath(const String16& filename, String16& path) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMountService: public BnInterface<IMountService> {
+public:
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags = 0);
+};
+
+}
+; // namespace android
+
+#endif // ANDROID_IMOUNTSERVICE_H
diff --git a/include/storage/IMountServiceListener.h b/include/storage/IMountServiceListener.h
new file mode 100644
index 0000000..5b1f21c
--- /dev/null
+++ b/include/storage/IMountServiceListener.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_IMOUNTSERVICELISTENER_H
+#define ANDROID_IMOUNTSERVICELISTENER_H
+
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class IMountServiceListener: public IInterface {
+public:
+ DECLARE_META_INTERFACE(MountServiceListener);
+
+ virtual void onUsbMassStorageConnectionChanged(const bool connected) = 0;
+ virtual void onStorageStateChanged(const String16& path,
+ const String16& oldState, const String16& newState) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMountServiceListener: public BnInterface<IMountServiceListener> {
+public:
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags = 0);
+};
+
+}
+; // namespace android
+
+#endif // ANDROID_IMOUNTSERVICELISTENER_H
diff --git a/include/storage/IMountShutdownObserver.h b/include/storage/IMountShutdownObserver.h
new file mode 100644
index 0000000..d019e01
--- /dev/null
+++ b/include/storage/IMountShutdownObserver.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_IMOUNTSHUTDOWNOBSERVER_H
+#define ANDROID_IMOUNTSHUTDOWNOBSERVER_H
+
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class IMountShutdownObserver: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(MountShutdownObserver);
+
+ virtual void onShutDownComplete(const int32_t statusCode) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMountShutdownObserver: public BnInterface<IMountShutdownObserver>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMOUNTSHUTDOWNOBSERVER_H
diff --git a/include/storage/IObbActionListener.h b/include/storage/IObbActionListener.h
new file mode 100644
index 0000000..1bedcc6
--- /dev/null
+++ b/include/storage/IObbActionListener.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_IOBBACTIONLISTENER_H
+#define ANDROID_IOBBACTIONLISTENER_H
+
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+#include <utils/String16.h>
+
+namespace android {
+
+class IObbActionListener: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(ObbActionListener);
+
+ virtual void onObbResult(const String16& filename, const String16& status) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnObbActionListener: public BnInterface<IObbActionListener>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IOBBACTIONLISTENER_H
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 294c867..6fdd2ae 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -94,7 +94,7 @@
friend class SurfaceComposerClient;
// camera and camcorder need access to the ISurface binder interface for preview
- friend class Camera;
+ friend class CameraService;
friend class MediaRecorder;
// mediaplayer needs access to ISurface for display
friend class MediaPlayer;
@@ -173,11 +173,12 @@
* (eventually this should go away and be replaced by proper APIs)
*/
// camera and camcorder need access to the ISurface binder interface for preview
- friend class Camera;
+ friend class CameraService;
friend class MediaRecorder;
// MediaPlayer needs access to ISurface for display
friend class MediaPlayer;
friend class IOMX;
+ friend class SoftwareRenderer;
// this is just to be able to write some unit tests
friend class Test;
@@ -309,4 +310,3 @@
}; // namespace android
#endif // ANDROID_SF_SURFACE_H
-
diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp
index 7efc6d7..b5f78e8 100644
--- a/libs/camera/Camera.cpp
+++ b/libs/camera/Camera.cpp
@@ -167,32 +167,20 @@
return c->unlock();
}
-// pass the buffered ISurface to the camera service
+// pass the buffered Surface to the camera service
status_t Camera::setPreviewDisplay(const sp<Surface>& surface)
{
- LOGV("setPreviewDisplay");
+ LOGV("setPreviewDisplay(%p)", surface.get());
sp <ICamera> c = mCamera;
if (c == 0) return NO_INIT;
if (surface != 0) {
- return c->setPreviewDisplay(surface->getISurface());
+ return c->setPreviewDisplay(surface);
} else {
LOGD("app passed NULL surface");
return c->setPreviewDisplay(0);
}
}
-status_t Camera::setPreviewDisplay(const sp<ISurface>& surface)
-{
- LOGV("setPreviewDisplay");
- if (surface == 0) {
- LOGD("app passed NULL surface");
- }
- sp <ICamera> c = mCamera;
- if (c == 0) return NO_INIT;
- return c->setPreviewDisplay(surface);
-}
-
-
// start preview mode
status_t Camera::startPreview()
{
@@ -375,4 +363,3 @@
}
}; // namespace android
-
diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
index abd418a..d0ed7df 100644
--- a/libs/camera/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -30,6 +30,8 @@
const char CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS[] = "preview-format-values";
const char CameraParameters::KEY_PREVIEW_FRAME_RATE[] = "preview-frame-rate";
const char CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES[] = "preview-frame-rate-values";
+const char CameraParameters::KEY_PREVIEW_FPS_RANGE[] = "preview-fps-range";
+const char CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE[] = "preview-fps-range-values";
const char CameraParameters::KEY_PICTURE_SIZE[] = "picture-size";
const char CameraParameters::KEY_SUPPORTED_PICTURE_SIZES[] = "picture-size-values";
const char CameraParameters::KEY_PICTURE_FORMAT[] = "picture-format";
@@ -269,20 +271,24 @@
mMap.removeItem(String8(key));
}
-static int parse_size(const char *str, int &width, int &height, char **endptr = NULL)
+// Parse string like "640x480" or "10000,20000"
+static int parse_pair(const char *str, int *first, int *second, char delim,
+ char **endptr = NULL)
{
- // Find the width.
+ // Find the first integer.
char *end;
int w = (int)strtol(str, &end, 10);
- // If an 'x' does not immediately follow, give up.
- if (*end != 'x')
+ // If a delimeter does not immediately follow, give up.
+ if (*end != delim) {
+ LOGE("Cannot find delimeter (%c) in str=%s", delim, str);
return -1;
+ }
- // Find the height, immediately after the 'x'.
+ // Find the second integer, immediately after the delimeter.
int h = (int)strtol(end+1, &end, 10);
- width = w;
- height = h;
+ *first = w;
+ *second = h;
if (endptr) {
*endptr = end;
@@ -301,7 +307,8 @@
while (true) {
int width, height;
- int success = parse_size(sizeStartPtr, width, height, &sizeStartPtr);
+ int success = parse_pair(sizeStartPtr, &width, &height, 'x',
+ &sizeStartPtr);
if (success == -1 || (*sizeStartPtr != ',' && *sizeStartPtr != '\0')) {
LOGE("Picture sizes string \"%s\" contains invalid character.", sizesStr);
return;
@@ -324,19 +331,11 @@
void CameraParameters::getPreviewSize(int *width, int *height) const
{
- *width = -1;
- *height = -1;
-
+ *width = *height = -1;
// Get the current string, if it doesn't exist, leave the -1x-1
const char *p = get(KEY_PREVIEW_SIZE);
- if (p == 0)
- return;
-
- int w, h;
- if (parse_size(p, w, h) == 0) {
- *width = w;
- *height = h;
- }
+ if (p == 0) return;
+ parse_pair(p, width, height, 'x');
}
void CameraParameters::getSupportedPreviewSizes(Vector<Size> &sizes) const
@@ -355,6 +354,14 @@
return getInt(KEY_PREVIEW_FRAME_RATE);
}
+void CameraParameters::getPreviewFpsRange(int *min_fps, int *max_fps) const
+{
+ *min_fps = *max_fps = -1;
+ const char *p = get(KEY_PREVIEW_FPS_RANGE);
+ if (p == 0) return;
+ parse_pair(p, min_fps, max_fps, ',');
+}
+
void CameraParameters::setPreviewFormat(const char *format)
{
set(KEY_PREVIEW_FORMAT, format);
@@ -374,19 +381,11 @@
void CameraParameters::getPictureSize(int *width, int *height) const
{
- *width = -1;
- *height = -1;
-
+ *width = *height = -1;
// Get the current string, if it doesn't exist, leave the -1x-1
const char *p = get(KEY_PICTURE_SIZE);
- if (p == 0)
- return;
-
- int w, h;
- if (parse_size(p, w, h) == 0) {
- *width = w;
- *height = h;
- }
+ if (p == 0) return;
+ parse_pair(p, width, height, 'x');
}
void CameraParameters::getSupportedPictureSizes(Vector<Size> &sizes) const
diff --git a/libs/camera/ICamera.cpp b/libs/camera/ICamera.cpp
index 13673b5..94dc5c1 100644
--- a/libs/camera/ICamera.cpp
+++ b/libs/camera/ICamera.cpp
@@ -64,13 +64,13 @@
remote()->transact(DISCONNECT, data, &reply);
}
- // pass the buffered ISurface to the camera service
- status_t setPreviewDisplay(const sp<ISurface>& surface)
+ // pass the buffered Surface to the camera service
+ status_t setPreviewDisplay(const sp<Surface>& surface)
{
LOGV("setPreviewDisplay");
Parcel data, reply;
data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
- data.writeStrongBinder(surface->asBinder());
+ Surface::writeToParcel(surface, &data);
remote()->transact(SET_PREVIEW_DISPLAY, data, &reply);
return reply.readInt32();
}
@@ -258,7 +258,7 @@
case SET_PREVIEW_DISPLAY: {
LOGV("SET_PREVIEW_DISPLAY");
CHECK_INTERFACE(ICamera, data, reply);
- sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder());
+ sp<Surface> surface = Surface::readFromParcel(data);
reply->writeInt32(setPreviewDisplay(surface));
return NO_ERROR;
} break;
@@ -376,4 +376,3 @@
// ----------------------------------------------------------------------------
}; // namespace android
-
diff --git a/libs/rs/java/Samples/res/drawable/torusmap.png b/libs/rs/java/Samples/res/drawable/torusmap.png
new file mode 100644
index 0000000..1e08f3b
--- /dev/null
+++ b/libs/rs/java/Samples/res/drawable/torusmap.png
Binary files differ
diff --git a/libs/rs/java/Samples/res/raw/torus.a3d b/libs/rs/java/Samples/res/raw/torus.a3d
new file mode 100644
index 0000000..610f095
--- /dev/null
+++ b/libs/rs/java/Samples/res/raw/torus.a3d
Binary files differ
diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
index 5a6ff23..8eff455 100644
--- a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
+++ b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
@@ -42,30 +42,40 @@
mOptionsARGB.inScaled = false;
mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
mMode = 0;
- mMaxModes = 4;
+ mMaxModes = 7;
initRS();
}
private Resources mRes;
private RenderScriptGL mRS;
- private Sampler mSampler;
+ private Sampler mLinearClamp;
+ private Sampler mLinearWrap;
+ private Sampler mMipLinearWrap;
+ private Sampler mNearestClamp;
+ private ProgramStore mProgStoreBlendNoneDepth;
private ProgramStore mProgStoreBlendNone;
private ProgramStore mProgStoreBlendAlpha;
private ProgramStore mProgStoreBlendAdd;
private ProgramFragment mProgFragmentTexture;
private ProgramFragment mProgFragmentColor;
+
private ProgramVertex mProgVertex;
private ProgramVertex.MatrixAllocation mPVA;
+ private ProgramRaster mCullBack;
+ private ProgramRaster mCullFront;
+
+ private Allocation mTexTorus;
private Allocation mTexOpaque;
private Allocation mTexTransparent;
private Allocation mAllocPV;
private Mesh mMbyNMesh;
+ private Mesh mTorus;
Font mFontSans;
Font mFontSerif;
@@ -89,10 +99,40 @@
mScript.set_gDisplayMode(mMode);
}
+ private Mesh getMbyNMesh(float width, float height, int wResolution, int hResolution) {
+
+ Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
+ 2, Mesh.TriangleMeshBuilder.TEXTURE_0);
+
+ for (int y = 0; y <= hResolution; y++) {
+ final float normalizedY = (float)y / hResolution;
+ final float yOffset = (normalizedY - 0.5f) * height;
+ for (int x = 0; x <= wResolution; x++) {
+ float normalizedX = (float)x / wResolution;
+ float xOffset = (normalizedX - 0.5f) * width;
+ tmb.setTexture(normalizedX, normalizedY);
+ tmb.addVertex(xOffset, yOffset);
+ }
+ }
+
+ for (int y = 0; y < hResolution; y++) {
+ final int curY = y * (wResolution + 1);
+ final int belowY = (y + 1) * (wResolution + 1);
+ for (int x = 0; x < wResolution; x++) {
+ int curV = curY + x;
+ int belowV = belowY + x;
+ tmb.addTriangle(curV, belowV, curV + 1);
+ tmb.addTriangle(belowV, belowV + 1, curV + 1);
+ }
+ }
+
+ return tmb.create(true);
+ }
private void initProgramStore() {
// Use stock the stock program store object
- mProgStoreBlendNone = ProgramStore.BlendNone_DepthNoDepth(mRS);
+ mProgStoreBlendNoneDepth = ProgramStore.BLEND_NONE_DEPTH_TEST(mRS);
+ mProgStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NO_DEPTH(mRS);
// Create a custom program store
ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
@@ -103,8 +143,9 @@
builder.setDepthMask(false);
mProgStoreBlendAlpha = builder.create();
- mProgStoreBlendAdd = ProgramStore.BlendAdd_DepthNoDepth(mRS);
+ mProgStoreBlendAdd = ProgramStore.BLEND_ADD_DEPTH_NO_DEPTH(mRS);
+ mScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
mScript.set_gProgStoreBlendNone(mProgStoreBlendNone);
mScript.set_gProgStoreBlendAlpha(mProgStoreBlendAlpha);
mScript.set_gProgStoreBlendAdd(mProgStoreBlendAdd);
@@ -112,18 +153,11 @@
private void initProgramFragment() {
- Sampler.Builder bs = new Sampler.Builder(mRS);
- bs.setMin(Sampler.Value.LINEAR);
- bs.setMag(Sampler.Value.LINEAR);
- bs.setWrapS(Sampler.Value.CLAMP);
- bs.setWrapT(Sampler.Value.CLAMP);
- mSampler = bs.create();
-
ProgramFragment.Builder texBuilder = new ProgramFragment.Builder(mRS);
texBuilder.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
ProgramFragment.Builder.Format.RGBA, 0);
mProgFragmentTexture = texBuilder.create();
- mProgFragmentTexture.bindSampler(mSampler, 0);
+ mProgFragmentTexture.bindSampler(mLinearClamp, 0);
ProgramFragment.Builder colBuilder = new ProgramFragment.Builder(mRS);
colBuilder.setVaryingColor(false);
@@ -146,22 +180,24 @@
private Allocation loadTextureRGB(int id) {
final Allocation allocation = Allocation.createFromBitmapResource(mRS, mRes,
- id, Element.RGB_565(mRS), false);
+ id, Element.RGB_565(mRS), true);
allocation.uploadToTexture(0);
return allocation;
}
private Allocation loadTextureARGB(int id) {
Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB);
- final Allocation allocation = Allocation.createFromBitmap(mRS, b, Element.RGBA_8888(mRS), false);
+ final Allocation allocation = Allocation.createFromBitmap(mRS, b, Element.RGBA_8888(mRS), true);
allocation.uploadToTexture(0);
return allocation;
}
private void loadImages() {
+ mTexTorus = loadTextureRGB(R.drawable.torusmap);
mTexOpaque = loadTextureRGB(R.drawable.data);
mTexTransparent = loadTextureARGB(R.drawable.leaf);
+ mScript.set_gTexTorus(mTexTorus);
mScript.set_gTexOpaque(mTexOpaque);
mScript.set_gTexTransparent(mTexTransparent);
}
@@ -185,19 +221,59 @@
mScript.set_gFontMono(mFontMono);
}
+ private void initMesh() {
+ mMbyNMesh = getMbyNMesh(256, 256, 10, 10);
+ mScript.set_gMbyNMesh(mMbyNMesh);
+
+ FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.torus);
+ FileA3D.IndexEntry entry = model.getIndexEntry(0);
+ if(entry == null || entry.getClassID() != FileA3D.ClassID.MESH) {
+ Log.e("rs", "could not load model");
+ }
+ else {
+ mTorus = (Mesh)entry.getObject();
+ mScript.set_gTorusMesh(mTorus);
+ }
+ }
+
+ private void initSamplers() {
+ Sampler.Builder bs = new Sampler.Builder(mRS);
+ bs.setMin(Sampler.Value.LINEAR);
+ bs.setMag(Sampler.Value.LINEAR);
+ bs.setWrapS(Sampler.Value.WRAP);
+ bs.setWrapT(Sampler.Value.WRAP);
+ mLinearWrap = bs.create();
+
+ mLinearClamp = Sampler.CLAMP_LINEAR(mRS);
+ mNearestClamp = Sampler.CLAMP_NEAREST(mRS);
+ mMipLinearWrap = Sampler.WRAP_LINEAR_MIP_LINEAR(mRS);
+
+ mScript.set_gLinearClamp(mLinearClamp);
+ mScript.set_gLinearWrap(mLinearWrap);
+ mScript.set_gMipLinearWrap(mMipLinearWrap);
+ mScript.set_gNearestClamp(mNearestClamp);
+ }
+
+ private void initProgramRaster() {
+ mCullBack = ProgramRaster.CULL_BACK(mRS);
+ mCullFront = ProgramRaster.CULL_FRONT(mRS);
+
+ mScript.set_gCullBack(mCullBack);
+ mScript.set_gCullFront(mCullFront);
+ }
+
private void initRS() {
mScript = new ScriptC_Rsrenderstates(mRS, mRes, R.raw.rsrenderstates, true);
+ initSamplers();
initProgramStore();
initProgramFragment();
initProgramVertex();
-
initFonts();
-
loadImages();
-
-
+ initMesh();
+ initProgramRaster();
mRS.contextBindRootScript(mScript);
}
diff --git a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs
index 1526a50..68d9d3c 100644
--- a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs
+++ b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs
@@ -22,14 +22,17 @@
rs_program_fragment gProgFragmentColor;
rs_program_fragment gProgFragmentTexture;
+rs_program_store gProgStoreBlendNoneDepth;
rs_program_store gProgStoreBlendNone;
rs_program_store gProgStoreBlendAlpha;
rs_program_store gProgStoreBlendAdd;
rs_allocation gTexOpaque;
+rs_allocation gTexTorus;
rs_allocation gTexTransparent;
rs_mesh gMbyNMesh;
+rs_mesh gTorusMesh;
rs_font gFontSans;
rs_font gFontSerif;
@@ -40,11 +43,21 @@
int gDisplayMode;
+rs_sampler gLinearClamp;
+rs_sampler gLinearWrap;
+rs_sampler gMipLinearWrap;
+rs_sampler gNearestClamp;
+
+rs_program_raster gCullBack;
+rs_program_raster gCullFront;
+
#pragma rs export_var(gProgVertex, gProgFragmentColor, gProgFragmentTexture)
-#pragma rs export_var(gProgStoreBlendNone, gProgStoreBlendAlpha, gProgStoreBlendAdd)
-#pragma rs export_var(gTexOpaque, gTexTransparent)
-#pragma rs export_var(gMbyNMesh)
+#pragma rs export_var(gProgStoreBlendNoneDepth, gProgStoreBlendNone, gProgStoreBlendAlpha, gProgStoreBlendAdd)
+#pragma rs export_var(gTexOpaque, gTexTorus, gTexTransparent)
+#pragma rs export_var(gMbyNMesh, gTorusMesh)
#pragma rs export_var(gFontSans, gFontSerif, gFontSerifBold, gFontSerifItalic, gFontSerifBoldItalic, gFontMono)
+#pragma rs export_var(gLinearClamp, gLinearWrap, gMipLinearWrap, gNearestClamp)
+#pragma rs export_var(gCullBack, gCullFront)
//What we are showing
#pragma rs export_var(gDisplayMode)
@@ -78,9 +91,17 @@
rsgDrawText("Monospace font sample", 30, yPos);
}
-void displayShaderSamples() {
+void bindProgramVertexOrtho() {
// Default vertex sahder
rsgBindProgramVertex(gProgVertex);
+ // Setup the projectioni matrix
+ rs_matrix4x4 proj;
+ rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -1,1);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+}
+
+void displayShaderSamples() {
+ bindProgramVertexOrtho();
rs_matrix4x4 matrix;
rsMatrixLoadIdentity(&matrix);
rsgProgramVertexLoadModelMatrix(&matrix);
@@ -88,24 +109,31 @@
// Fragment shader with texture
rsgBindProgramStore(gProgStoreBlendNone);
rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
- rsgDrawQuadTexCoords(0, 0, 0, 0, 0,
- 0, 256, 0, 0, 1,
- 256, 256, 0, 1, 1,
- 256, 0, 0, 1, 0);
+ float startX = 0, startY = 0;
+ float width = 256, height = 256;
+ rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+ startX, startY + height, 0, 0, 1,
+ startX + width, startY + height, 0, 1, 1,
+ startX + width, startY, 0, 1, 0);
- rsgDrawQuadTexCoords(200, 0, 0, 0, 0,
- 200, 128, 0, 0, 1,
- 328, 128, 0, 1, 1,
- 328, 0, 0, 1, 0);
+ startX = 200; startY = 0;
+ width = 128; height = 128;
+ rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+ startX, startY + height, 0, 0, 1,
+ startX + width, startY + height, 0, 1, 1,
+ startX + width, startY, 0, 1, 0);
rsgBindProgramStore(gProgStoreBlendAlpha);
rsgBindTexture(gProgFragmentTexture, 0, gTexTransparent);
- rsgDrawQuadTexCoords(0, 200, 0, 0, 0,
- 0, 328, 0, 0, 1,
- 128, 328, 0, 1, 1,
- 128, 200, 0, 1, 0);
+ startX = 0; startY = 200;
+ width = 128; height = 128;
+ rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+ startX, startY + height, 0, 0, 1,
+ startX + width, startY + height, 0, 1, 1,
+ startX + width, startY, 0, 1, 0);
// Fragment program with simple color
rsgBindProgramFragment(gProgFragmentColor);
@@ -124,7 +152,7 @@
void displayBlendingSamples() {
int i;
- rsgBindProgramVertex(gProgVertex);
+ bindProgramVertexOrtho();
rs_matrix4x4 matrix;
rsMatrixLoadIdentity(&matrix);
rsgProgramVertexLoadModelMatrix(&matrix);
@@ -168,11 +196,128 @@
}
void displayMeshSamples() {
+
+ bindProgramVertexOrtho();
+ rs_matrix4x4 matrix;
+ rsMatrixLoadTranslate(&matrix, 128, 128, 0);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+
+ // Fragment shader with texture
+ rsgBindProgramStore(gProgStoreBlendNone);
+ rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+ rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
+
+ rsgDrawMesh(gMbyNMesh);
+
+ rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+ rsgBindFont(gFontMono);
+ rsgDrawText("User gen 10 by 10 grid mesh", 10, 250);
+}
+
+void displayTextureSamplers() {
+
+ bindProgramVertexOrtho();
+ rs_matrix4x4 matrix;
+ rsMatrixLoadIdentity(&matrix);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+
+ // Fragment shader with texture
+ rsgBindProgramStore(gProgStoreBlendNone);
+ rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
+
+ // Linear clamp
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+ float startX = 0, startY = 0;
+ float width = 300, height = 300;
+ rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+ startX, startY + height, 0, 0, 1.1,
+ startX + width, startY + height, 0, 1.1, 1.1,
+ startX + width, startY, 0, 1.1, 0);
+
+ // Linear Wrap
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearWrap);
+ startX = 0; startY = 300;
+ width = 300; height = 300;
+ rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+ startX, startY + height, 0, 0, 1.1,
+ startX + width, startY + height, 0, 1.1, 1.1,
+ startX + width, startY, 0, 1.1, 0);
+
+ // Nearest
+ rsgBindSampler(gProgFragmentTexture, 0, gNearestClamp);
+ startX = 300; startY = 0;
+ width = 300; height = 300;
+ rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+ startX, startY + height, 0, 0, 1.1,
+ startX + width, startY + height, 0, 1.1, 1.1,
+ startX + width, startY, 0, 1.1, 0);
+
+ rsgBindSampler(gProgFragmentTexture, 0, gMipLinearWrap);
+ startX = 300; startY = 300;
+ width = 300; height = 300;
+ rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+ startX, startY + height, 0, 0, 1.5,
+ startX + width, startY + height, 0, 1.5, 1.5,
+ startX + width, startY, 0, 1.5, 0);
+
+
+ rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+ rsgBindFont(gFontMono);
+ rsgDrawText("Filtering: linear clamp", 10, 290);
+ rsgDrawText("Filtering: linear wrap", 10, 590);
+ rsgDrawText("Filtering: nearest clamp", 310, 290);
+ rsgDrawText("Filtering: miplinear wrap", 310, 590);
+
+}
+
+float gTorusRotation = 0;
+
+void displayCullingSamplers() {
+ rsgBindProgramVertex(gProgVertex);
+ // Setup the projectioni matrix with 60 degree field of view
+ rs_matrix4x4 proj;
+ float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+ rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+
+ // Fragment shader with texture
+ rsgBindProgramStore(gProgStoreBlendNoneDepth);
+ rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+ rsgBindTexture(gProgFragmentTexture, 0, gTexTorus);
+
+ // Aplly a rotation to our mesh
+ gTorusRotation += 50.0f * rsGetDt();
+ if(gTorusRotation > 360.0f) {
+ gTorusRotation -= 360.0f;
+ }
+
+ rs_matrix4x4 matrix;
+ // Position our model on the screen
+ rsMatrixLoadTranslate(&matrix, -2.0f, 0.0f, -10.0f);
+ rsMatrixRotate(&matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+ // Use front face culling
+ rsgBindProgramRaster(gCullFront);
+ rsgDrawMesh(gTorusMesh);
+
+ rsMatrixLoadTranslate(&matrix, 2.0f, 0.0f, -10.0f);
+ rsMatrixRotate(&matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+ // Use back face culling
+ rsgBindProgramRaster(gCullBack);
+ rsgDrawMesh(gTorusMesh);
+
+ rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+ rsgBindFont(gFontMono);
+ rsgDrawText("Displaying mesh front/back face culling", 10, rsgGetHeight() - 10);
}
int root(int launchID) {
- rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
rsgClearDepth(1.0f);
switch(gDisplayMode) {
@@ -188,6 +333,12 @@
case 3:
displayMeshSamples();
break;
+ case 4:
+ displayTextureSamplers();
+ break;
+ case 5:
+ displayCullingSamplers();
+ break;
}
return 10;
diff --git a/libs/storage/Android.mk b/libs/storage/Android.mk
new file mode 100644
index 0000000..1e52fa4
--- /dev/null
+++ b/libs/storage/Android.mk
@@ -0,0 +1,20 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ IMountServiceListener.cpp \
+ IMountShutdownObserver.cpp \
+ IObbActionListener.cpp \
+ IMountService.cpp
+
+LOCAL_STATIC_LIBRARIES := \
+ libutils \
+ libbinder
+
+LOCAL_MODULE:= libstorage
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -lpthread
+endif
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp
new file mode 100644
index 0000000..902bb27
--- /dev/null
+++ b/libs/storage/IMountService.cpp
@@ -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.
+ */
+
+#define LOG_TAG "IMountService"
+
+#include <storage/IMountService.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+enum {
+ TRANSACTION_registerListener = IBinder::FIRST_CALL_TRANSACTION,
+ TRANSACTION_unregisterListener,
+ TRANSACTION_isUsbMassStorageConnected,
+ TRANSACTION_setUsbMassStorageEnabled,
+ TRANSACTION_isUsbMassStorageEnabled,
+ TRANSACTION_mountVolume,
+ TRANSACTION_unmountVolume,
+ TRANSACTION_formatVolume,
+ TRANSACTION_getStorageUsers,
+ TRANSACTION_getVolumeState,
+ TRANSACTION_createSecureContainer,
+ TRANSACTION_finalizeSecureContainer,
+ TRANSACTION_destroySecureContainer,
+ TRANSACTION_mountSecureContainer,
+ TRANSACTION_unmountSecureContainer,
+ TRANSACTION_isSecureContainerMounted,
+ TRANSACTION_renameSecureContainer,
+ TRANSACTION_getSecureContainerPath,
+ TRANSACTION_getSecureContainerList,
+ TRANSACTION_shutdown,
+ TRANSACTION_finishMediaUpdate,
+ TRANSACTION_mountObb,
+ TRANSACTION_unmountObb,
+ TRANSACTION_isObbMounted,
+ TRANSACTION_getMountedObbPath,
+};
+
+class BpMountService: public BpInterface<IMountService>
+{
+public:
+ BpMountService(const sp<IBinder>& impl)
+ : BpInterface<IMountService>(impl)
+ {
+ }
+
+ virtual void registerListener(const sp<IMountServiceListener>& listener)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeStrongBinder(listener->asBinder());
+ if (remote()->transact(TRANSACTION_registerListener, data, &reply) != NO_ERROR) {
+ LOGD("registerListener could not contact remote\n");
+ return;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("registerListener caught exception %d\n", err);
+ return;
+ }
+ }
+
+ virtual void unregisterListener(const sp<IMountServiceListener>& listener)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeStrongBinder(listener->asBinder());
+ if (remote()->transact(TRANSACTION_unregisterListener, data, &reply) != NO_ERROR) {
+ LOGD("unregisterListener could not contact remote\n");
+ return;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("unregisterListener caught exception %d\n", err);
+ return;
+ }
+ }
+
+ virtual bool isUsbMassStorageConnected()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ if (remote()->transact(TRANSACTION_isUsbMassStorageConnected, data, &reply) != NO_ERROR) {
+ LOGD("isUsbMassStorageConnected could not contact remote\n");
+ return false;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("isUsbMassStorageConnected caught exception %d\n", err);
+ return false;
+ }
+ return reply.readInt32() != 0;
+ }
+
+ virtual void setUsbMassStorageEnabled(const bool enable)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeInt32(enable != 0);
+ if (remote()->transact(TRANSACTION_setUsbMassStorageEnabled, data, &reply) != NO_ERROR) {
+ LOGD("setUsbMassStorageEnabled could not contact remote\n");
+ return;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("setUsbMassStorageEnabled caught exception %d\n", err);
+ return;
+ }
+ }
+
+ virtual bool isUsbMassStorageEnabled()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ if (remote()->transact(TRANSACTION_isUsbMassStorageEnabled, data, &reply) != NO_ERROR) {
+ LOGD("isUsbMassStorageEnabled could not contact remote\n");
+ return false;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("isUsbMassStorageEnabled caught exception %d\n", err);
+ return false;
+ }
+ return reply.readInt32() != 0;
+ }
+
+ int32_t mountVolume(const String16& mountPoint)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(mountPoint);
+ if (remote()->transact(TRANSACTION_mountVolume, data, &reply) != NO_ERROR) {
+ LOGD("mountVolume could not contact remote\n");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("mountVolume caught exception %d\n", err);
+ return err;
+ }
+ return reply.readInt32();
+ }
+
+ int32_t unmountVolume(const String16& mountPoint, const bool force)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(mountPoint);
+ data.writeInt32(force ? 1 : 0);
+ if (remote()->transact(TRANSACTION_unmountVolume, data, &reply) != NO_ERROR) {
+ LOGD("unmountVolume could not contact remote\n");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("unmountVolume caught exception %d\n", err);
+ return err;
+ }
+ return reply.readInt32();
+ }
+
+ int32_t formatVolume(const String16& mountPoint)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(mountPoint);
+ if (remote()->transact(TRANSACTION_formatVolume, data, &reply) != NO_ERROR) {
+ LOGD("formatVolume could not contact remote\n");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("formatVolume caught exception %d\n", err);
+ return err;
+ }
+ return reply.readInt32();
+ }
+
+ int32_t getStorageUsers(const String16& mountPoint, int32_t** users)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(mountPoint);
+ if (remote()->transact(TRANSACTION_getStorageUsers, data, &reply) != NO_ERROR) {
+ LOGD("getStorageUsers could not contact remote\n");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("getStorageUsers caught exception %d\n", err);
+ return err;
+ }
+ const int32_t numUsers = reply.readInt32();
+ *users = (int32_t*)malloc(sizeof(int32_t)*numUsers);
+ for (int i = 0; i < numUsers; i++) {
+ **users++ = reply.readInt32();
+ }
+ return numUsers;
+ }
+
+ int32_t getVolumeState(const String16& mountPoint)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(mountPoint);
+ if (remote()->transact(TRANSACTION_getVolumeState, data, &reply) != NO_ERROR) {
+ LOGD("getVolumeState could not contact remote\n");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("getVolumeState caught exception %d\n", err);
+ return err;
+ }
+ return reply.readInt32();
+ }
+
+ int32_t createSecureContainer(const String16& id, const int32_t sizeMb, const String16& fstype,
+ const String16& key, const int32_t ownerUid)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(id);
+ data.writeInt32(sizeMb);
+ data.writeString16(fstype);
+ data.writeString16(key);
+ data.writeInt32(ownerUid);
+ if (remote()->transact(TRANSACTION_createSecureContainer, data, &reply) != NO_ERROR) {
+ LOGD("createSecureContainer could not contact remote\n");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("createSecureContainer caught exception %d\n", err);
+ return err;
+ }
+ return reply.readInt32();
+ }
+
+ int32_t finalizeSecureContainer(const String16& id)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(id);
+ if (remote()->transact(TRANSACTION_finalizeSecureContainer, data, &reply) != NO_ERROR) {
+ LOGD("finalizeSecureContainer couldn't call remote\n");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("finalizeSecureContainer caught exception %d\n", err);
+ return err;
+ }
+ return reply.readInt32();
+ }
+
+ int32_t destroySecureContainer(const String16& id)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(id);
+ if (remote()->transact(TRANSACTION_destroySecureContainer, data, &reply) != NO_ERROR) {
+ LOGD("destroySecureContainer couldn't call remote");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("destroySecureContainer caught exception %d\n", err);
+ return err;
+ }
+ return reply.readInt32();
+ }
+
+ int32_t mountSecureContainer(const String16& id, const String16& key, const int32_t ownerUid)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(id);
+ data.writeString16(key);
+ data.writeInt32(ownerUid);
+ if (remote()->transact(TRANSACTION_mountSecureContainer, data, &reply) != NO_ERROR) {
+ LOGD("mountSecureContainer couldn't call remote");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode(); // What to do...
+ if (err < 0) {
+ LOGD("mountSecureContainer caught exception %d\n", err);
+ return err;
+ }
+ return reply.readInt32();
+ }
+
+ int32_t unmountSecureContainer(const String16& id, const bool force)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(id);
+ data.writeInt32(force ? 1 : 0);
+ if (remote()->transact(TRANSACTION_getSecureContainerPath, data, &reply) != NO_ERROR) {
+ LOGD("unmountSecureContainer couldn't call remote");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode(); // What to do...
+ if (err < 0) {
+ LOGD("unmountSecureContainer caught exception %d\n", err);
+ return err;
+ }
+ return reply.readInt32();
+ }
+
+ bool isSecureContainerMounted(const String16& id)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(id);
+ if (remote()->transact(TRANSACTION_isSecureContainerMounted, data, &reply) != NO_ERROR) {
+ LOGD("isSecureContainerMounted couldn't call remote");
+ return false;
+ }
+ int32_t err = reply.readExceptionCode(); // What to do...
+ if (err < 0) {
+ LOGD("isSecureContainerMounted caught exception %d\n", err);
+ return false;
+ }
+ return reply.readInt32() != 0;
+ }
+
+ int32_t renameSecureContainer(const String16& oldId, const String16& newId)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(oldId);
+ data.writeString16(newId);
+ if (remote()->transact(TRANSACTION_renameSecureContainer, data, &reply) != NO_ERROR) {
+ LOGD("renameSecureContainer couldn't call remote");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode(); // What to do...
+ if (err < 0) {
+ LOGD("renameSecureContainer caught exception %d\n", err);
+ return err;
+ }
+ return reply.readInt32();
+ }
+
+ bool getSecureContainerPath(const String16& id, String16& path)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(id);
+ if (remote()->transact(TRANSACTION_getSecureContainerPath, data, &reply) != NO_ERROR) {
+ LOGD("getSecureContainerPath couldn't call remote");
+ return false;
+ }
+ int32_t err = reply.readExceptionCode(); // What to do...
+ if (err < 0) {
+ LOGD("getSecureContainerPath caught exception %d\n", err);
+ return false;
+ }
+ path = reply.readString16();
+ return true;
+ }
+
+ int32_t getSecureContainerList(const String16& id, String16*& containers)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(id);
+ if (remote()->transact(TRANSACTION_getSecureContainerList, data, &reply) != NO_ERROR) {
+ LOGD("getSecureContainerList couldn't call remote");
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("getSecureContainerList caught exception %d\n", err);
+ return err;
+ }
+ const int32_t numStrings = reply.readInt32();
+ containers = new String16[numStrings];
+ for (int i = 0; i < numStrings; i++) {
+ containers[i] = reply.readString16();
+ }
+ return numStrings;
+ }
+
+ void shutdown(const sp<IMountShutdownObserver>& observer)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeStrongBinder(observer->asBinder());
+ if (remote()->transact(TRANSACTION_shutdown, data, &reply) != NO_ERROR) {
+ LOGD("shutdown could not contact remote\n");
+ return;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("shutdown caught exception %d\n", err);
+ return;
+ }
+ reply.readExceptionCode();
+ }
+
+ void finishMediaUpdate()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ if (remote()->transact(TRANSACTION_finishMediaUpdate, data, &reply) != NO_ERROR) {
+ LOGD("finishMediaUpdate could not contact remote\n");
+ return;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("finishMediaUpdate caught exception %d\n", err);
+ return;
+ }
+ reply.readExceptionCode();
+ }
+
+ void mountObb(const String16& filename, const String16& key, const sp<
+ IObbActionListener>& token)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(filename);
+ data.writeString16(key);
+ data.writeStrongBinder(token->asBinder());
+ if (remote()->transact(TRANSACTION_mountObb, data, &reply) != NO_ERROR) {
+ LOGD("mountObb could not contact remote\n");
+ return;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("mountObb caught exception %d\n", err);
+ return;
+ }
+ }
+
+ void unmountObb(const String16& filename, const bool force)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(filename);
+ data.writeInt32(force ? 1 : 0);
+ if (remote()->transact(TRANSACTION_unmountObb, data, &reply) != NO_ERROR) {
+ LOGD("unmountObb could not contact remote\n");
+ return;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("unmountObb caught exception %d\n", err);
+ return;
+ }
+ }
+
+ bool isObbMounted(const String16& filename)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(filename);
+ if (remote()->transact(TRANSACTION_isObbMounted, data, &reply) != NO_ERROR) {
+ LOGD("isObbMounted could not contact remote\n");
+ return false;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("isObbMounted caught exception %d\n", err);
+ return false;
+ }
+ return reply.readInt32() != 0;
+ }
+
+ bool getMountedObbPath(const String16& filename, String16& path)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+ data.writeString16(filename);
+ if (remote()->transact(TRANSACTION_getMountedObbPath, data, &reply) != NO_ERROR) {
+ LOGD("getMountedObbPath could not contact remote\n");
+ return false;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ LOGD("getMountedObbPath caught exception %d\n", err);
+ return false;
+ }
+ path = reply.readString16();
+ return true;
+ }
+};
+
+IMPLEMENT_META_INTERFACE(MountService, "IMountService");
+
+// ----------------------------------------------------------------------
+
+};
diff --git a/libs/storage/IMountServiceListener.cpp b/libs/storage/IMountServiceListener.cpp
new file mode 100644
index 0000000..c98a424
--- /dev/null
+++ b/libs/storage/IMountServiceListener.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#include <storage/IMountServiceListener.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+enum {
+ TRANSACTION_onUsbMassStorageConnectionChanged = IBinder::FIRST_CALL_TRANSACTION,
+ TRANSACTION_onStorageStateChanged,
+};
+
+status_t BnMountServiceListener::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case TRANSACTION_onUsbMassStorageConnectionChanged: {
+ CHECK_INTERFACE(IMountServiceListener, data, reply);
+ bool connected = (data.readInt32() != 0);
+ onUsbMassStorageConnectionChanged(connected);
+ reply->writeNoException();
+ return NO_ERROR;
+ } break;
+ case TRANSACTION_onStorageStateChanged: {
+ CHECK_INTERFACE(IMountServiceListener, data, reply);
+ String16 path = data.readString16();
+ String16 oldState = data.readString16();
+ String16 newState = data.readString16();
+ onStorageStateChanged(path, oldState, newState);
+ reply->writeNoException();
+ return NO_ERROR;
+ }
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+// ----------------------------------------------------------------------
+
+};
diff --git a/libs/storage/IMountShutdownObserver.cpp b/libs/storage/IMountShutdownObserver.cpp
new file mode 100644
index 0000000..1a6fdee
--- /dev/null
+++ b/libs/storage/IMountShutdownObserver.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#include <storage/IMountShutdownObserver.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+enum {
+ TRANSACTION_onShutDownComplete = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+status_t BnMountShutdownObserver::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case TRANSACTION_onShutDownComplete: {
+ CHECK_INTERFACE(IMountShutdownObserver, data, reply);
+ int32_t statusCode = data.readInt32();
+ onShutDownComplete(statusCode);
+ reply->writeNoException();
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+// ----------------------------------------------------------------------
+
+};
diff --git a/libs/storage/IObbActionListener.cpp b/libs/storage/IObbActionListener.cpp
new file mode 100644
index 0000000..5bfece7
--- /dev/null
+++ b/libs/storage/IObbActionListener.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#include <storage/IObbActionListener.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+enum {
+ TRANSACTION_onObbResult = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+// This is a stub that real consumers should override.
+class BpObbActionListener: public BpInterface<IObbActionListener> {
+public:
+ BpObbActionListener(const sp<IBinder>& impl)
+ : BpInterface<IObbActionListener>(impl)
+ { }
+
+ virtual void onObbResult(const String16& filename, const String16& status) { }
+};
+
+IMPLEMENT_META_INTERFACE(ObbActionListener, "IObbActionListener");
+
+// ----------------------------------------------------------------------
+
+status_t BnObbActionListener::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case TRANSACTION_onObbResult: {
+ CHECK_INTERFACE(IObbActionListener, data, reply);
+ String16 filename = data.readString16();
+ String16 state = data.readString16();
+ onObbResult(filename, state);
+ reply->writeNoException();
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------
+
+};
diff --git a/libs/storage/MODULE_LICENSE_APACHE2 b/libs/storage/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/storage/MODULE_LICENSE_APACHE2
diff --git a/libs/storage/NOTICE b/libs/storage/NOTICE
new file mode 100644
index 0000000..5d14293
--- /dev/null
+++ b/libs/storage/NOTICE
@@ -0,0 +1,190 @@
+
+ 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 156a7db..47ec78a 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -344,11 +344,6 @@
{
SharedBufferStack& stack( *mSharedStack );
- if (stack.head == tail && stack.available == mNumBuffers) {
- LOGW("dequeue: tail=%d, head=%d, avail=%d, queued=%d",
- tail, stack.head, stack.available, stack.queued);
- }
-
RWLock::AutoRLock _rd(mLock);
const nsecs_t dequeueTime = systemTime(SYSTEM_TIME_THREAD);
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 5ab72cd..f524476 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -363,6 +363,13 @@
height = surface->mHeight;
format = surface->mFormat;
flags = surface->mFlags;
+ } else if (surface != 0 && surface->mSurface != 0) {
+ LOGW("Parceling invalid surface with non-NULL ISurface as NULL: "
+ "mSurface = %p, mIdentity = %d, mWidth = %d, mHeight = %d, "
+ "mFormat = %d, mFlags = 0x%08x, mInitCheck = %d",
+ surface->mSurface.get(), surface->mIdentity, surface->mWidth,
+ surface->mHeight, surface->mFormat, surface->mFlags,
+ surface->mInitCheck);
}
parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
parcel->writeInt32(identity);
@@ -434,6 +441,9 @@
mSharedBufferClient = new SharedBufferClient(
mClient.getSharedClient(), token, 2, mIdentity);
mInitCheck = mClient.getSharedClient()->validate(token);
+ } else {
+ LOGW("Not initializing the shared buffer client because token = %d",
+ token);
}
}
}
diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp
index a4c3500..604f558 100644
--- a/libs/utils/ZipFileRO.cpp
+++ b/libs/utils/ZipFileRO.cpp
@@ -636,7 +636,7 @@
memcpy(buffer, ptr, uncompLen);
} else {
if (!inflateBuffer(buffer, ptr, uncompLen, compLen))
- goto bail;
+ goto unmap;
}
if (compLen > kSequentialMin)
@@ -644,6 +644,8 @@
result = true;
+unmap:
+ file->release();
bail:
return result;
}
@@ -667,7 +669,7 @@
getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL);
- const FileMap* file = createEntryFileMap(entry);
+ FileMap* file = createEntryFileMap(entry);
if (file == NULL) {
goto bail;
}
@@ -678,21 +680,23 @@
ssize_t actual = write(fd, ptr, uncompLen);
if (actual < 0) {
LOGE("Write failed: %s\n", strerror(errno));
- goto bail;
+ goto unmap;
} else if ((size_t) actual != uncompLen) {
LOGE("Partial write during uncompress (%zd of %zd)\n",
(size_t)actual, (size_t)uncompLen);
- goto bail;
+ goto unmap;
} else {
LOGI("+++ successful write\n");
}
} else {
if (!inflateBuffer(fd, ptr, uncompLen, compLen))
- goto bail;
+ goto unmap;
}
result = true;
+unmap:
+ file->release();
bail:
return result;
}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 7f91c22..7d8ef58 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -556,7 +556,8 @@
mTitle = value;
} else if (name.equalsIgnoreCase("artist") || name.startsWith("artist;")) {
mArtist = value.trim();
- } else if (name.equalsIgnoreCase("albumartist") || name.startsWith("albumartist;")) {
+ } else if (name.equalsIgnoreCase("albumartist") || name.startsWith("albumartist;")
+ || name.equalsIgnoreCase("band") || name.startsWith("band;")) {
mAlbumArtist = value.trim();
} else if (name.equalsIgnoreCase("album") || name.startsWith("album;")) {
mAlbum = value.trim();
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index abbea30..bf83172 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -118,6 +118,18 @@
MtpObjectHandleList* references);
};
+// ----------------------------------------------------------------------------
+
+static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
+ if (env->ExceptionCheck()) {
+ LOGE("An exception was thrown by callback '%s'.", methodName);
+ LOGE_EX(env);
+ env->ExceptionClear();
+ }
+}
+
+// ----------------------------------------------------------------------------
+
MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client)
: mDatabase(env->NewGlobalRef(client)),
mIntBuffer(NULL),
@@ -165,8 +177,12 @@
uint64_t size,
time_t modified) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
- return env->CallIntMethod(mDatabase, method_beginSendObject, env->NewStringUTF(path),
- (jint)format, (jint)parent, (jint)storage, (jlong)size, (jlong)modified);
+ MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
+ env->NewStringUTF(path), (jint)format, (jint)parent, (jint)storage,
+ (jlong)size, (jlong)modified);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return result;
}
void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
@@ -174,6 +190,8 @@
JNIEnv* env = AndroidRuntime::getJNIEnv();
env->CallVoidMethod(mDatabase, method_endSendObject, env->NewStringUTF(path),
(jint)handle, (jint)format, (jboolean)succeeded);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
}
MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
@@ -189,16 +207,21 @@
jsize length = env->GetArrayLength(array);
for (int i = 0; i < length; i++)
list->push(handles[i]);
- env->ReleaseIntArrayElements(array, handles, 0);
- return list;
+ env->ReleaseIntArrayElements(array, handles, 0);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return list;
}
int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
MtpObjectFormat format,
MtpObjectHandle parent) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
- return env->CallIntMethod(mDatabase, method_getNumObjects,
+ int result = env->CallIntMethod(mDatabase, method_getNumObjects,
(jint)storageID, (jint)format, (jint)parent);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return result;
}
MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
@@ -212,8 +235,10 @@
jsize length = env->GetArrayLength(array);
for (int i = 0; i < length; i++)
list->push(formats[i]);
- env->ReleaseIntArrayElements(array, formats, 0);
- return list;
+ env->ReleaseIntArrayElements(array, formats, 0);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return list;
}
MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
@@ -227,8 +252,10 @@
jsize length = env->GetArrayLength(array);
for (int i = 0; i < length; i++)
list->push(formats[i]);
- env->ReleaseIntArrayElements(array, formats, 0);
- return list;
+ env->ReleaseIntArrayElements(array, formats, 0);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return list;
}
MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
@@ -242,8 +269,10 @@
jsize length = env->GetArrayLength(array);
for (int i = 0; i < length; i++)
list->push(properties[i]);
- env->ReleaseIntArrayElements(array, properties, 0);
- return list;
+ env->ReleaseIntArrayElements(array, properties, 0);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return list;
}
MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
@@ -257,8 +286,10 @@
jsize length = env->GetArrayLength(array);
for (int i = 0; i < length; i++)
list->push(properties[i]);
- env->ReleaseIntArrayElements(array, properties, 0);
- return list;
+ env->ReleaseIntArrayElements(array, properties, 0);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return list;
}
MtpResponseCode MyMtpDatabase::getObjectProperty(MtpObjectHandle handle,
@@ -315,6 +346,8 @@
LOGE("unsupported object type\n");
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
}
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
return MTP_RESPONSE_OK;
}
@@ -368,6 +401,7 @@
packet.putString(date); // date modified
packet.putEmptyString(); // keywords
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
return MTP_RESPONSE_OK;
}
@@ -388,12 +422,16 @@
fileLength = longValues[0];
env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
return result;
}
MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
- return env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
+ MtpResponseCode result = env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return result;
}
struct PropertyTableEntry {
@@ -433,11 +471,14 @@
jsize length = env->GetArrayLength(array);
for (int i = 0; i < length; i++)
list->push(handles[i]);
- env->ReleaseIntArrayElements(array, handles, 0);
- return list;
+ env->ReleaseIntArrayElements(array, handles, 0);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return list;
}
-MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle, MtpObjectHandleList* references) {
+MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
+ MtpObjectHandleList* references) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
int count = references->size();
jintArray array = env->NewIntArray(count);
@@ -449,18 +490,11 @@
for (int i = 0; i < count; i++)
handles[i] = (*references)[i];
env->ReleaseIntArrayElements(array, handles, 0);
- return env->CallIntMethod(mDatabase, method_setObjectReferences,
+ MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
(jint)handle, array);
-}
-// ----------------------------------------------------------------------------
-
-static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
- if (env->ExceptionCheck()) {
- LOGE("An exception was thrown by callback '%s'.", methodName);
- LOGE_EX(env);
- env->ExceptionClear();
- }
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return result;
}
#endif // HAVE_ANDROID_OS
diff --git a/media/libeffects/lvm/lib/Android.mk b/media/libeffects/lvm/lib/Android.mk
index a944212..ff34707 100644
--- a/media/libeffects/lvm/lib/Android.mk
+++ b/media/libeffects/lvm/lib/Android.mk
@@ -122,3 +122,58 @@
$(LOCAL_PATH)/StereoWidening/lib
include $(BUILD_STATIC_LIBRARY)
+
+# Reverb library
+include $(CLEAR_VARS)
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_SRC_FILES:= \
+ Reverb/src/LVREV_ApplyNewSettings.c \
+ Reverb/src/LVREV_ClearAudioBuffers.c \
+ Reverb/src/LVREV_GetControlParameters.c \
+ Reverb/src/LVREV_GetInstanceHandle.c \
+ Reverb/src/LVREV_GetMemoryTable.c \
+ Reverb/src/LVREV_Process.c \
+ Reverb/src/LVREV_SetControlParameters.c \
+ Reverb/src/LVREV_Tables.c \
+ Common/src/Abs_32.c \
+ Common/src/InstAlloc.c \
+ Common/src/LoadConst_16.c \
+ Common/src/LoadConst_32.c \
+ Common/src/From2iToMono_32.c \
+ Common/src/Mult3s_32x16.c \
+ Common/src/FO_1I_D32F32C31_TRC_WRA_01.c \
+ Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c \
+ Common/src/DelayAllPass_Sat_32x16To32.c \
+ Common/src/Copy_16.c \
+ Common/src/Mac3s_Sat_32x16.c \
+ Common/src/DelayWrite_32.c \
+ Common/src/Shift_Sat_v32xv32.c \
+ Common/src/Add2_Sat_32x32.c \
+ Common/src/JoinTo2i_32x32.c \
+ Common/src/MonoTo2I_32.c \
+ Common/src/LVM_FO_HPF.c \
+ Common/src/LVM_FO_LPF.c \
+ Common/src/LVM_Polynomial.c \
+ Common/src/LVM_Power10.c \
+ Common/src/LVM_GetOmega.c \
+ Common/src/MixSoft_2St_D32C31_SAT.c \
+ Common/src/MixSoft_1St_D32C31_WRA.c \
+ Common/src/MixInSoft_D32C31_SAT.c \
+ Common/src/LVM_Mixer_TimeConstant.c \
+ Common/src/Core_MixHard_2St_D32C31_SAT.c \
+ Common/src/Core_MixSoft_1St_D32C31_WRA.c \
+ Common/src/Core_MixInSoft_D32C31_SAT.c
+
+LOCAL_MODULE:= libreverb
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/Reverb/lib \
+ $(LOCAL_PATH)/Reverb/src \
+ $(LOCAL_PATH)/Common/lib \
+ $(LOCAL_PATH)/Common/src
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
index 8cf84b7..4a9dc72 100755
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
@@ -17,9 +17,9 @@
/****************************************************************************************
- $Author: nxp007753 $
- $Revision: 1315 $
- $Date: 2010-07-23 11:52:08 +0200 (Fri, 23 Jul 2010) $
+ $Author: beq06068 $
+ $Revision: 1401 $
+ $Date: 2010-08-03 09:52:22 +0200 (Tue, 03 Aug 2010) $
*****************************************************************************************/
@@ -128,7 +128,7 @@
(void *)&pInstance->pData->HPFTaps, /* Destination Cast to void: \
no dereferencing in function*/
sizeof(pInstance->pData->HPFTaps)/sizeof(LVM_INT16)); /* Number of words */
- BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance, /* Initialise the filter */
+ BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance, /* Initialise the filter */
&pInstance->pData->HPFTaps,
(BQ_C32_Coefs_t *)&LVDBE_HPF_Table[Offset]);
@@ -140,7 +140,7 @@
(void *)&pInstance->pData->BPFTaps, /* Destination Cast to void:\
no dereferencing in function*/
sizeof(pInstance->pData->BPFTaps)/sizeof(LVM_INT16)); /* Number of words */
- BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */
+ BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */
&pInstance->pData->BPFTaps,
(BP_C32_Coefs_t *)&LVDBE_BPF_Table[Offset]);
@@ -317,6 +317,7 @@
{
LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
+ LVMixer3_2St_st *pBypassMixer_Instance = &pInstance->pData->BypassMixer;
/*
@@ -339,6 +340,14 @@
{
LVDBE_SetAGC(pInstance, /* Instance pointer */
pParams); /* New parameters */
+
+ LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
+ LVDBE_BYPASS_MIXER_TC,pParams->SampleRate,2);
+
+ LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
+ LVDBE_BYPASS_MIXER_TC,pParams->SampleRate,2);
+
+
}
@@ -356,17 +365,13 @@
if (pInstance->Params.OperatingMode==LVDBE_ON && pParams->OperatingMode==LVDBE_OFF)
{
- LVDBE_Params_t Params = *pParams; /* make local copy of params */
- Params.EffectLevel = 0; /* zero effect level before switching off module*/
- pInstance->bTransitionOnToOff = LVM_TRUE; /* Set the CallBack */
- LVDBE_SetAGC(pInstance, /* Instance pointer */
- &Params); /* New parameters */
+ LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0);
+ LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0x00007FFF);
}
if (pInstance->Params.OperatingMode==LVDBE_OFF && pParams->OperatingMode==LVDBE_ON)
{
- pInstance->bTransitionOnToOff = LVM_FALSE; /* Set the CallBack */
- LVDBE_SetAGC(pInstance, /* Instance pointer */
- pParams); /* New parameters */
+ LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0x00007FFF);
+ LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0);
}
/*
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
index 75869c7..95c421d 100755
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
@@ -17,9 +17,9 @@
/****************************************************************************************
- $Author: nxp007753 $
- $Revision: 1081 $
- $Date: 2010-07-05 11:48:44 +0200 (Mon, 05 Jul 2010) $
+ $Author: beq06068 $
+ $Revision: 1399 $
+ $Date: 2010-08-03 08:16:00 +0200 (Tue, 03 Aug 2010) $
*****************************************************************************************/
@@ -160,6 +160,7 @@
LVDBE_Instance_t *pInstance;
LVMixer3_1St_st *pMixer_Instance;
+ LVMixer3_2St_st *pBypassMixer_Instance;
LVM_INT16 i;
LVM_INT32 MixGain;
@@ -227,7 +228,7 @@
/*
* Initialise the filters
*/
- LVDBE_SetFilters(pInstance, /* Set the filter taps and coefficients */
+ LVDBE_SetFilters(pInstance, /* Set the filter taps and coefficients */
&pInstance->Params);
@@ -236,7 +237,8 @@
*/
LVDBE_SetAGC(pInstance, /* Set the AGC gain */
&pInstance->Params);
- pInstance->pData->AGCInstance.AGC_Gain = pInstance->pData->AGCInstance.AGC_MaxGain; /* Default to the bass boost setting */
+ pInstance->pData->AGCInstance.AGC_Gain = pInstance->pData->AGCInstance.AGC_MaxGain;
+ /* Default to the bass boost setting */
/*
@@ -245,7 +247,8 @@
LVDBE_SetVolume(pInstance, /* Set the Volume */
&pInstance->Params);
- pInstance->pData->AGCInstance.Volume = pInstance->pData->AGCInstance.Target; /* Initialise as the target */
+ pInstance->pData->AGCInstance.Volume = pInstance->pData->AGCInstance.Target;
+ /* Initialise as the target */
pMixer_Instance = &pInstance->pData->BypassVolume;
MixGain = LVC_Mixer_GetTarget(&pMixer_Instance->MixerStream[0]);
@@ -258,9 +261,31 @@
pMixer_Instance->MixerStream[0].CallbackSet = 0;
/*
- * Initialise the clicks minimisation variable
+ * Initialise the clicks minimisation BypassMixer
*/
- pInstance->bTransitionOnToOff = LVM_FALSE;
+
+ pBypassMixer_Instance = &pInstance->pData->BypassMixer;
+
+ /*
+ * Setup the mixer gain for the processed path
+ */
+ pBypassMixer_Instance->MixerStream[0].CallbackParam = 0;
+ pBypassMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
+ pBypassMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
+ pBypassMixer_Instance->MixerStream[0].CallbackSet=0;
+ LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[0],0,0);
+ LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
+ LVDBE_BYPASS_MIXER_TC,pInstance->Params.SampleRate,2);
+ /*
+ * Setup the mixer gain for the unprocessed path
+ */
+ pBypassMixer_Instance->MixerStream[1].CallbackParam = 0;
+ pBypassMixer_Instance->MixerStream[1].pCallbackHandle = LVM_NULL;
+ pBypassMixer_Instance->MixerStream[1].pCallBack = LVM_NULL;
+ pBypassMixer_Instance->MixerStream[1].CallbackSet=0;
+ LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[1],0x00007FFF,0x00007FFF);
+ LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
+ LVDBE_BYPASS_MIXER_TC,pInstance->Params.SampleRate,2);
return(LVDBE_SUCCESS);
}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
index 3e09cf4..df32873 100755
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -17,9 +17,9 @@
/****************************************************************************************
- $Author: nxp007753 $
- $Revision: 1081 $
- $Date: 2010-07-05 11:48:44 +0200 (Mon, 05 Jul 2010) $
+ $Author: beq06068 $
+ $Revision: 1399 $
+ $Date: 2010-08-03 08:16:00 +0200 (Tue, 03 Aug 2010) $
*****************************************************************************************/
@@ -75,6 +75,8 @@
#define LVDBE_SCRATCHBUFFERS_INPLACE 4 /* Number of buffers required for inplace processing */
#define LVDBE_MIXER_TC 5 /* Mixer time */
+#define LVDBE_BYPASS_MIXER_TC 100 /* Bypass mixer time */
+
/****************************************************************************************/
/* */
@@ -92,6 +94,7 @@
Biquad_2I_Order2_Taps_t HPFTaps; /* High pass filter taps */
Biquad_1I_Order2_Taps_t BPFTaps; /* Band pass filter taps */
LVMixer3_1St_st BypassVolume; /* Bypass volume scaler */
+ LVMixer3_2St_st BypassMixer; /* Bypass Mixer for Click Removal */
} LVDBE_Data_t;
@@ -115,9 +118,6 @@
/* Data and coefficient pointers */
LVDBE_Data_t *pData; /* Instance data */
LVDBE_Coef_t *pCoef; /* Instance coefficients */
-
- LVM_INT32 bTransitionOnToOff;
-
} LVDBE_Instance_t;
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
index 35eec07..04032c0 100755
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
@@ -17,9 +17,9 @@
/****************************************************************************************
- $Author: nxp007753 $
- $Revision: 1081 $
- $Date: 2010-07-05 11:48:44 +0200 (Mon, 05 Jul 2010) $
+ $Author: beq06068 $
+ $Revision: 1400 $
+ $Date: 2010-08-03 09:22:37 +0200 (Tue, 03 Aug 2010) $
*****************************************************************************************/
@@ -89,10 +89,16 @@
LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
LVM_INT32 *pScratch = (LVM_INT32 *)pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress;
- LVM_INT32 *pMono = (LVM_INT32 *)pOutData;
+ LVM_INT32 *pMono;
LVM_INT16 *pInput = (LVM_INT16 *)pInData;
+ /* Scratch for Volume Control starts at offset of 2*NumSamples short values from pScratch */
+ LVM_INT16 *pScratchVol = (LVM_INT16 *)(&pScratch[NumSamples]);
+
+ /* Scratch for Mono path starts at offset of 2*NumSamples 32-bit values from pScratch */
+ pMono = &pScratch[2*NumSamples];
+
/*
* Check the number of samples is not too large
*/
@@ -104,18 +110,20 @@
/*
* Check if the algorithm is enabled
*/
- if ((pInstance->Params.OperatingMode != LVDBE_OFF) ||
- (pInstance->bTransitionOnToOff == LVM_TRUE))
+ /* DBE path is processed when DBE is ON or during On/Off transitions */
+ if ((pInstance->Params.OperatingMode == LVDBE_ON)||
+ (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0])
+ !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0])))
{
/*
* Convert 16-bit samples to 32-bit and scale
* (For a 16-bit implementation apply headroom loss here)
*/
- Int16LShiftToInt32_16x32(pInput, /* Source 16-bit data */
- pScratch, /* Destination 32-bit data */
- (LVM_INT16)(2*NumSamples), /* Left and right */
- LVDBE_SCALESHIFT); /* Shift scale */
+ Int16LShiftToInt32_16x32(pInput, /* Source 16-bit data */
+ pScratch, /* Dest. 32-bit data */
+ (LVM_INT16)(2*NumSamples), /* Left and right */
+ LVDBE_SCALESHIFT); /* Shift scale */
/*
@@ -123,61 +131,54 @@
*/
if (pInstance->Params.HPFSelect == LVDBE_HPF_ON)
{
- BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance, /* Filter instance */
- (LVM_INT32 *)pScratch, /* Source */
- (LVM_INT32 *)pScratch, /* Destination */
- (LVM_INT16)NumSamples); /* Number of samples */
+ BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance */
+ (LVM_INT32 *)pScratch, /* Source */
+ (LVM_INT32 *)pScratch, /* Destination */
+ (LVM_INT16)NumSamples); /* Number of samples */
}
/*
* Create the mono stream
*/
- From2iToMono_32(pScratch, /* Stereo source */
- pMono, /* Mono destination */
- (LVM_INT16)NumSamples); /* Number of samples */
+ From2iToMono_32(pScratch, /* Stereo source */
+ pMono, /* Mono destination */
+ (LVM_INT16)NumSamples); /* Number of samples */
/*
* Apply the band pass filter
*/
- BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */
- (LVM_INT32 *)pMono, /* Source */
- (LVM_INT32 *)pMono, /* Destination */
- (LVM_INT16)NumSamples); /* Number of samples */
+ BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */
+ (LVM_INT32 *)pMono, /* Source */
+ (LVM_INT32 *)pMono, /* Destination */
+ (LVM_INT16)NumSamples); /* Number of samples */
/*
* Apply the AGC and mix
*/
- AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */
- pScratch, /* Stereo source */
- pMono, /* Mono band pass source */
- pScratch, /* Stereo destination */
- NumSamples); /* Number of samples */
-
- if(pInstance->bTransitionOnToOff == LVM_TRUE)
- {
- if ((pInstance->pData->AGCInstance.AGC_Gain == pInstance->pData->AGCInstance.AGC_Target)&&
- (pInstance->pData->AGCInstance.AGC_Gain == 0))
- {
- pInstance->bTransitionOnToOff = LVM_FALSE;
- }
- }
-
-
+ AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */
+ pScratch, /* Stereo source */
+ pMono, /* Mono band pass source */
+ pScratch, /* Stereo destination */
+ NumSamples); /* Number of samples */
/*
* Convert 32-bit samples to 16-bit and saturate
* (Not required for 16-bit implemenations)
*/
- Int32RShiftToInt16_Sat_32x16(pScratch, /* Source 32-bit data */
- pOutData, /* Destination 16-bit data */
- (LVM_INT16)(2*NumSamples), /* Left and right */
- LVDBE_SCALESHIFT); /* Shift scale */
+ Int32RShiftToInt16_Sat_32x16(pScratch, /* Source 32-bit data */
+ (LVM_INT16 *)pScratch, /* Dest. 16-bit data */
+ (LVM_INT16)(2*NumSamples), /* Left and right */
+ LVDBE_SCALESHIFT); /* Shift scale */
}
- else
+
+ /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
+ if ((pInstance->Params.OperatingMode == LVDBE_OFF)||
+ (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[1])
+ !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[1])))
{
/*
@@ -186,11 +187,20 @@
*/
LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume,
pInData,
- pOutData,
- (LVM_INT16)(2*NumSamples)); /* Left and right */
+ pScratchVol,
+ (LVM_INT16)(2*NumSamples)); /* Left and right */
}
+ /*
+ * Mix DBE processed path and bypass volume path
+ */
+ LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
+ (LVM_INT16 *) pScratch,
+ pScratchVol,
+ pOutData,
+ (LVM_INT16)(2*NumSamples));
+
return(LVDBE_SUCCESS);
}
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
index 922f77d..cec7501 100755
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
@@ -18,8 +18,8 @@
/****************************************************************************************
$Author: nxp007753 $
- $Revision: 1316 $
- $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $
+ $Revision: 1331 $
+ $Date: 2010-07-27 12:26:23 +0200 (Tue, 27 Jul 2010) $
*****************************************************************************************/
diff --git a/media/libeffects/lvm/lib/Reverb/lib/LVREV.h b/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
new file mode 100755
index 0000000..4c32db0
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * 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.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq03888 $*/
+/* $Revision: 1204 $*/
+/* $Date: 2010-07-14 08:55:43 +0200 (Wed, 14 Jul 2010) $*/
+/* */
+/************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Header file for the application layer interface of the LVREV module */
+/* */
+/* This files includes all definitions, types, structures and function prototypes */
+/* required by the calling layer. All other types, structures and functions are */
+/* private. */
+/* */
+/****************************************************************************************/
+
+#ifndef __LVREV_H__
+#define __LVREV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVM_Types.h"
+
+
+/****************************************************************************************/
+/* */
+/* Definitions */
+/* */
+/****************************************************************************************/
+/* General */
+#define LVREV_BLOCKSIZE_MULTIPLE 1 /* Processing block size multiple */
+#define LVREV_MAX_T60 7000 /* Maximum decay time is 7000ms */
+
+/* Memory table*/
+#define LVREV_NR_MEMORY_REGIONS 4 /* Number of memory regions */
+
+
+/****************************************************************************************/
+/* */
+/* Types */
+/* */
+/****************************************************************************************/
+/* Instance handle */
+typedef void *LVREV_Handle_t;
+
+
+/* Status return values */
+typedef enum
+{
+ LVREV_SUCCESS = 0, /* Successful return from a routine */
+ LVREV_NULLADDRESS = 1, /* NULL allocation address */
+ LVREV_OUTOFRANGE = 2, /* Out of range control parameter */
+ LVREV_INVALIDNUMSAMPLES = 3, /* Invalid number of samples */
+ LVREV_RETURNSTATUS_DUMMY = LVM_MAXENUM
+} LVREV_ReturnStatus_en;
+
+
+/* Reverb delay lines */
+typedef enum
+{
+ LVREV_DELAYLINES_1 = 1, /* One delay line */
+ LVREV_DELAYLINES_2 = 2, /* Two delay lines */
+ LVREV_DELAYLINES_4 = 4, /* Four delay lines */
+ LVREV_DELAYLINES_DUMMY = LVM_MAXENUM
+} LVREV_NumDelayLines_en;
+
+
+/****************************************************************************************/
+/* */
+/* Structures */
+/* */
+/****************************************************************************************/
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+ LVM_MemoryRegion_st Region[LVREV_NR_MEMORY_REGIONS]; /* One definition for each region */
+} LVREV_MemoryTable_st;
+
+
+/* Control Parameter structure */
+typedef struct
+{
+ /* General parameters */
+ LVM_Mode_en OperatingMode; /* Operating mode */
+ LVM_Fs_en SampleRate; /* Sample rate */
+ LVM_Format_en SourceFormat; /* Source data format */
+
+ /* Parameters for REV */
+ LVM_UINT16 Level; /* Level, 0 to 100 representing percentage of reverb */
+ LVM_UINT16 LPF; /* Low pass filter, in Hz */
+ LVM_UINT16 HPF; /* High pass filter, in Hz */
+ LVM_UINT16 T60; /* Decay time constant, in ms */
+ LVM_UINT16 Density; /* Echo density, 0 to 100 for minimum to maximum density */
+ LVM_UINT16 Damping; /* Damping */
+ LVM_UINT16 RoomSize; /* Simulated room size, 1 to 100 for minimum to maximum size */
+
+} LVREV_ControlParams_st;
+
+
+/* Instance Parameter structure */
+typedef struct
+{
+ /* General */
+ LVM_UINT16 MaxBlockSize; /* Maximum processing block size */
+
+ /* Reverb */
+ LVM_Format_en SourceFormat; /* Source data formats to support */
+ LVREV_NumDelayLines_en NumDelays; /* The number of delay lines, 1, 2 or 4 */
+
+} LVREV_InstanceParams_st;
+
+
+/****************************************************************************************/
+/* */
+/* Function Prototypes */
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_GetMemoryTable */
+/* */
+/* DESCRIPTION: */
+/* This function is used to obtain the LVREV module memory requirements to support */
+/* memory allocation. It can also be used to return the memory base address provided */
+/* during memory allocation to support freeing of memory when the LVREV module is no */
+/* longer required. It is called in two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and allocated */
+/* base addresses. */
+/* */
+/* When this function is called with hInstance = NULL the memory base address pointers */
+/* will be NULL on return. */
+/* */
+/* When the function is called for freeing memory, hInstance = Instance Handle the */
+/* memory table returns the allocated memory and base addresses used during */
+/* initialisation. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pMemoryTable Pointer to an empty memory table */
+/* pInstanceParams Pointer to the instance parameters */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Succeeded */
+/* LVREV_NULLADDRESS When pMemoryTable is NULL */
+/* LVREV_NULLADDRESS When requesting memory requirements and pInstanceParams */
+/* is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetMemoryTable(LVREV_Handle_t hInstance,
+ LVREV_MemoryTable_st *pMemoryTable,
+ LVREV_InstanceParams_st *pInstanceParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_GetInstanceHandle */
+/* */
+/* DESCRIPTION: */
+/* This function is used to create a LVREV module instance. It returns the created */
+/* instance handle through phInstance. All parameters are set to invalid values, the */
+/* LVREV_SetControlParameters function must be called with a set of valid control */
+/* parameters before the LVREV_Process function can be called. */
+/* */
+/* The memory allocation must be provided by the application by filling in the memory */
+/* region base addresses in the memory table before calling this function. */
+/* */
+/* PARAMETERS: */
+/* phInstance Pointer to the instance handle */
+/* pMemoryTable Pointer to the memory definition table */
+/* pInstanceParams Pointer to the instance parameters */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Succeeded */
+/* LVREV_NULLADDRESS When phInstance or pMemoryTable or pInstanceParams is NULL */
+/* LVREV_NULLADDRESS When one of the memory regions has a NULL pointer */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetInstanceHandle(LVREV_Handle_t *phInstance,
+ LVREV_MemoryTable_st *pMemoryTable,
+ LVREV_InstanceParams_st *pInstanceParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVXX_GetControlParameters */
+/* */
+/* DESCRIPTION: */
+/* Request the LVREV module control parameters. The current parameter set is returned */
+/* via the parameter pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pControlParams Pointer to an empty parameter structure */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Succeeded */
+/* LVREV_NULLADDRESS When hInstance or pControlParams is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetControlParameters(LVREV_Handle_t hInstance,
+ LVREV_ControlParams_st *pControlParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_SetControlParameters */
+/* */
+/* DESCRIPTION: */
+/* Sets or changes the LVREV module parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pNewParams Pointer to a parameter structure */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Succeeded */
+/* LVREV_NULLADDRESS When hInstance or pNewParams is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_SetControlParameters(LVREV_Handle_t hInstance,
+ LVREV_ControlParams_st *pNewParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_ClearAudioBuffers */
+/* */
+/* DESCRIPTION: */
+/* This function is used to clear the internal audio buffers of the module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Initialisation succeeded */
+/* LVREV_NULLADDRESS Instance is NULL */
+/* */
+/* NOTES: */
+/* 1. This function must not be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_ClearAudioBuffers(LVREV_Handle_t hInstance);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the LVREV module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Succeeded */
+/* LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size */
+/* */
+/* NOTES: */
+/* 1. The input and output buffers must be 32-bit aligned */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t hInstance,
+ const LVM_INT32 *pInData,
+ LVM_INT32 *pOutData,
+ const LVM_UINT16 NumSamples);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVREV_H__ */
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c
new file mode 100755
index 0000000..0026652
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c
@@ -0,0 +1,656 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Project:: */
+/* $Author: nxp007753 $ */
+/* $Revision: 1316 $ */
+/* $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $ */
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "Filter.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_ApplyNewSettings */
+/* */
+/* DESCRIPTION: */
+/* Applies the new control parameters */
+/* */
+/* PARAMETERS: */
+/* pPrivate Pointer to the instance private parameters */
+/* */
+/* RETURNS: */
+/* LVREV_Success Succeeded */
+/* LVREV_NULLADDRESS When pPrivate is NULL */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+LVREV_ReturnStatus_en LVREV_ApplyNewSettings (LVREV_Instance_st *pPrivate)
+{
+
+ LVM_Mode_en OperatingMode;
+ LVM_INT32 NumberOfDelayLines;
+
+
+ /* Check for NULL pointer */
+ if(pPrivate == LVM_NULL)
+ {
+ return LVREV_NULLADDRESS;
+ }
+
+ OperatingMode = pPrivate->NewParams.OperatingMode;
+
+ if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+ {
+ NumberOfDelayLines = 4;
+ }
+ else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
+ {
+ NumberOfDelayLines = 2;
+ }
+ else
+ {
+ NumberOfDelayLines = 1;
+ }
+
+ /*
+ * Update the high pass filter coefficients
+ */
+ if((pPrivate->NewParams.HPF != pPrivate->CurrentParams.HPF) ||
+ (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+ LVM_INT32 Omega;
+ FO_C32_Coefs_t Coeffs;
+
+ Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
+ LVM_FO_HPF(Omega, &Coeffs);
+ FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->HPCoefs, &pPrivate->pFastData->HPTaps, &Coeffs);
+ LoadConst_32(0,
+ (void *)&pPrivate->pFastData->HPTaps, /* Destination Cast to void: no dereferencing in function*/
+ sizeof(Biquad_1I_Order1_Taps_t)/sizeof(LVM_INT32));
+ }
+
+
+ /*
+ * Update the low pass filter coefficients
+ */
+ if((pPrivate->NewParams.LPF != pPrivate->CurrentParams.LPF) ||
+ (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+ LVM_INT32 Omega;
+ FO_C32_Coefs_t Coeffs;
+
+
+ Coeffs.A0 = 0x7FFFFFFF;
+ Coeffs.A1 = 0;
+ Coeffs.B1 = 0;
+ if(pPrivate->NewParams.LPF <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
+ {
+ Omega = LVM_GetOmega(pPrivate->NewParams.LPF, pPrivate->NewParams.SampleRate);
+
+ /*
+ * Do not apply filter if w =2*pi*fc/fs >= 2.9
+ */
+ if(Omega<=LVREV_2_9_INQ29)
+ {
+ LVM_FO_LPF(Omega, &Coeffs);
+ }
+ }
+ FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->LPCoefs, &pPrivate->pFastData->LPTaps, &Coeffs);
+ LoadConst_32(0,
+ (void *)&pPrivate->pFastData->LPTaps, /* Destination Cast to void: no dereferencing in function*/
+ sizeof(Biquad_1I_Order1_Taps_t)/sizeof(LVM_INT32));
+ }
+
+
+ /*
+ * Calculate the room size parameter
+ */
+ if( pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize)
+ {
+ /* Room size range is 10ms to 200ms
+ * 0% -- 10ms
+ * 50% -- 65ms
+ * 100% -- 120ms
+ */
+ pPrivate->RoomSizeInms = 10 + (((pPrivate->NewParams.RoomSize*11) + 5)/10);
+ }
+
+
+ /*
+ * Update the T delay number of samples and the all pass delay number of samples
+ */
+ if( (pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
+ (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+
+ LVM_UINT32 Temp;
+ LVM_INT32 APDelaySize;
+ LVM_INT32 Fs = LVM_GetFsFromTable(pPrivate->NewParams.SampleRate);
+ LVM_UINT32 DelayLengthSamples = (LVM_UINT32)(Fs * pPrivate->RoomSizeInms);
+ LVM_INT16 i;
+ LVM_INT16 ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
+ LVM_INT16 MaxT_Delay[] = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, LVREV_MAX_T2_DELAY, LVREV_MAX_T3_DELAY};
+ LVM_INT16 MaxAP_Delay[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY, LVREV_MAX_AP2_DELAY, LVREV_MAX_AP3_DELAY};
+
+
+ /*
+ * For each delay line
+ */
+ for (i=0; i<NumberOfDelayLines; i++)
+ {
+ if (i != 0)
+ {
+ LVM_INT32 Temp1; /* to avoid QAC warning on type conversion */
+ LVM_INT32 Temp2; /* to avoid QAC warning on type conversion */
+
+ Temp2=(LVM_INT32)DelayLengthSamples;
+ MUL32x16INTO32(Temp2, ScaleTable[i], Temp1, 15)
+ Temp=(LVM_UINT32)Temp1;
+ }
+ else
+ {
+ Temp = DelayLengthSamples;
+ }
+ APDelaySize = Temp / 1500;
+
+
+ /*
+ * Set the fixed delay
+ */
+ Temp = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 48000;
+ pPrivate->Delay_AP[i] = pPrivate->T[i] - Temp;
+
+
+ /*
+ * Set the tap selection
+ */
+ if (pPrivate->AB_Selection)
+ {
+ /* Smooth from tap A to tap B */
+ pPrivate->pOffsetB[i] = &pPrivate->pDelay_T[i][pPrivate->T[i] - Temp - APDelaySize];
+ pPrivate->B_DelaySize[i] = APDelaySize;
+ pPrivate->Mixer_APTaps[i].Target1 = 0;
+ pPrivate->Mixer_APTaps[i].Target2 = 0x7fffffff;
+ }
+ else
+ {
+ /* Smooth from tap B to tap A */
+ pPrivate->pOffsetA[i] = &pPrivate->pDelay_T[i][pPrivate->T[i] - Temp - APDelaySize];
+ pPrivate->A_DelaySize[i] = APDelaySize;
+ pPrivate->Mixer_APTaps[i].Target2 = 0;
+ pPrivate->Mixer_APTaps[i].Target1 = 0x7fffffff;
+ }
+
+ /*
+ * Set the maximum block size to the smallest delay size
+ */
+ pPrivate->MaxBlkLen = Temp;
+ if (pPrivate->MaxBlkLen > pPrivate->A_DelaySize[i])
+ {
+ pPrivate->MaxBlkLen = pPrivate->A_DelaySize[i];
+ }
+ if (pPrivate->MaxBlkLen > pPrivate->B_DelaySize[i])
+ {
+ pPrivate->MaxBlkLen = pPrivate->B_DelaySize[i];
+ }
+ }
+ if (pPrivate->AB_Selection)
+ {
+ pPrivate->AB_Selection = 0;
+ }
+ else
+ {
+ pPrivate->AB_Selection = 1;
+ }
+
+
+ /*
+ * Limit the maximum block length
+ */
+ pPrivate->MaxBlkLen=pPrivate->MaxBlkLen-2; /* Just as a precausion, but no problem if we remove this line */
+ if(pPrivate->MaxBlkLen > pPrivate->InstanceParams.MaxBlockSize)
+ {
+ pPrivate->MaxBlkLen = (LVM_INT32)pPrivate->InstanceParams.MaxBlockSize;
+ }
+ }
+
+
+ /*
+ * Update the low pass filter coefficient
+ */
+ if( (pPrivate->NewParams.Damping != pPrivate->CurrentParams.Damping) ||
+ (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+
+ LVM_INT32 Temp;
+ LVM_INT32 Omega;
+ FO_C32_Coefs_t Coeffs;
+ LVM_INT16 i;
+ LVM_INT16 Damping = (LVM_INT16)((pPrivate->NewParams.Damping * 100) + 1000);
+ LVM_INT32 ScaleTable[] = {LVREV_T_3_Power_0_on_4, LVREV_T_3_Power_1_on_4, LVREV_T_3_Power_2_on_4, LVREV_T_3_Power_3_on_4};
+
+
+ /*
+ * For each filter
+ */
+ for (i=0; i<NumberOfDelayLines; i++)
+ {
+ if (i != 0)
+ {
+ MUL32x16INTO32(ScaleTable[i], Damping, Temp, 15)
+ }
+ else
+ {
+ Temp = Damping;
+ }
+ if(Temp <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
+ {
+ Omega = LVM_GetOmega((LVM_UINT16)Temp, pPrivate->NewParams.SampleRate);
+ LVM_FO_LPF(Omega, &Coeffs);
+ }
+ else
+ {
+ Coeffs.A0 = 0x7FF00000;
+ Coeffs.A1 = 0;
+ Coeffs.B1 = 0;
+ }
+ FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i], &pPrivate->pFastData->RevLPTaps[i], &Coeffs);
+ }
+ }
+
+
+ /*
+ * Update All-pass filter mixer time constants
+ */
+ if( (pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
+ (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->NewParams.Density != pPrivate->CurrentParams.Density))
+ {
+ LVM_INT16 i;
+ LVM_INT32 Alpha = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_ALLPASS_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), 1);
+ LVM_INT32 AlphaTap = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_ALLPASS_TAP_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), 1);
+
+ for (i=0; i<4; i++)
+ {
+ pPrivate->Mixer_APTaps[i].Alpha1 = AlphaTap;
+ pPrivate->Mixer_APTaps[i].Alpha2 = AlphaTap;
+ pPrivate->Mixer_SGFeedback[i].Alpha = Alpha;
+ pPrivate->Mixer_SGFeedforward[i].Alpha = Alpha;
+ }
+ }
+
+
+ /*
+ * Update the feed back gain
+ */
+ if( (pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
+ (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->NewParams.T60 != pPrivate->CurrentParams.T60) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+
+ LVM_INT32 G[4]; /* Feedback gain (Q7.24) */
+
+ if(pPrivate->NewParams.T60 == 0)
+ {
+ G[3] = 0;
+ G[2] = 0;
+ G[1] = 0;
+ G[0] = 0;
+ }
+ else
+ {
+ LVM_INT32 Temp1;
+ LVM_INT32 Temp2;
+ LVM_INT16 i;
+ LVM_INT16 ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
+
+
+ /*
+ * For each delay line
+ */
+ for (i=0; i<NumberOfDelayLines; i++)
+ {
+ Temp1 = (3 * pPrivate->RoomSizeInms * ScaleTable[i]) / pPrivate->NewParams.T60;
+ if(Temp1 >= (4 << 15))
+ {
+ G[i] = 0;
+ }
+ else if((Temp1 >= (2 << 15)))
+ {
+ Temp2 = LVM_Power10(-(Temp1 << 14));
+ Temp1 = LVM_Power10(-(Temp1 << 14));
+ MUL32x32INTO32(Temp1,Temp2,Temp1,24)
+ }
+ else
+ {
+ Temp1 = LVM_Power10(-(Temp1 << 15));
+ }
+ if (NumberOfDelayLines == 1)
+ {
+ G[i] = Temp1;
+ }
+ else
+ {
+ LVM_INT32 TempG;
+ MUL32x16INTO32(Temp1,ONE_OVER_SQRT_TWO,TempG,15)
+ G[i]=TempG;
+ }
+ }
+ }
+
+ /* Set up the feedback mixers for four delay lines */
+ pPrivate->FeedbackMixer[0].Target=G[0]<<7;
+ pPrivate->FeedbackMixer[1].Target=G[1]<<7;
+ pPrivate->FeedbackMixer[2].Target=G[2]<<7;
+ pPrivate->FeedbackMixer[3].Target=G[3]<<7;
+ }
+
+
+ /*
+ * Calculate the gain correction
+ */
+ if((pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
+ (pPrivate->NewParams.Level != pPrivate->CurrentParams.Level) ||
+ (pPrivate->NewParams.T60 != pPrivate->CurrentParams.T60) )
+ {
+ LVM_INT32 Index=0;
+ LVM_INT32 i=0;
+ LVM_INT32 Gain=0;
+ LVM_INT32 RoomSize=0;
+ LVM_INT32 T60;
+ LVM_INT32 Coefs[5];
+
+ if(pPrivate->NewParams.RoomSize==0)
+ {
+ RoomSize=1;
+ }
+ else
+ {
+ RoomSize=(LVM_INT32)pPrivate->NewParams.RoomSize;
+ }
+
+ if(pPrivate->NewParams.T60<100)
+ {
+ T60 = 100 * LVREV_T60_SCALE;
+ }
+ else
+ {
+ T60 = pPrivate->NewParams.T60 * LVREV_T60_SCALE;
+ }
+
+ /* Find the nearest room size in table */
+ for(i=0;i<24;i++)
+ {
+ if(RoomSize<= LVREV_GainPolyTable[i][0])
+ {
+ Index=i;
+ break;
+ }
+ }
+
+
+ if(RoomSize==LVREV_GainPolyTable[Index][0])
+ {
+ /* Take table values if the room size is in table */
+ for(i=1;i<5;i++)
+ {
+ Coefs[i-1]=LVREV_GainPolyTable[Index][i];
+ }
+ Coefs[4]=0;
+ Gain=LVM_Polynomial(3,Coefs,T60); /* Q.24 result */
+ }
+ else
+ {
+ /* Interpolate the gain between nearest room sizes */
+
+ LVM_INT32 Gain1,Gain2;
+ LVM_INT32 Tot_Dist,Dist;
+
+ Tot_Dist=LVREV_GainPolyTable[Index][0]-LVREV_GainPolyTable[Index-1][0];
+ Dist=RoomSize-LVREV_GainPolyTable[Index-1][0];
+
+
+ /* Get gain for first */
+ for(i=1;i<5;i++)
+ {
+ Coefs[i-1]=LVREV_GainPolyTable[Index-1][i];
+ }
+ Coefs[4]=0;
+
+ Gain1=LVM_Polynomial(3,Coefs,T60); /* Q.24 result */
+
+ /* Get gain for second */
+ for(i=1;i<5;i++)
+ {
+ Coefs[i-1]=LVREV_GainPolyTable[Index][i];
+ }
+ Coefs[4]=0;
+
+ Gain2=LVM_Polynomial(3,Coefs,T60); /* Q.24 result */
+
+ /* Linear Interpolate the gain */
+ Gain = Gain1+ (((Gain2-Gain1)*Dist)/(Tot_Dist));
+ }
+
+
+ /*
+ * Get the inverse of gain: Q.15
+ * Gain is mostly above one except few cases, take only gains above 1
+ */
+ if(Gain < 16777216L)
+ {
+ pPrivate->Gain= 32767;
+ }
+ else
+ {
+ pPrivate->Gain=(LVM_INT16)(LVM_MAXINT_32/(Gain>>8));
+ }
+
+
+ Index=((32767*100)/(100+pPrivate->NewParams.Level));
+ pPrivate->Gain=(LVM_INT16)((pPrivate->Gain*Index)>>15);
+ pPrivate->GainMixer.Target = pPrivate->Gain*Index;
+ }
+
+
+ /*
+ * Update the all pass comb filter coefficient
+ */
+ if( (pPrivate->NewParams.Density != pPrivate->CurrentParams.Density) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+ LVM_INT16 i;
+ LVM_INT32 b = pPrivate->NewParams.Density * LVREV_B_8_on_1000;
+
+ for (i=0;i<4; i++)
+ {
+ pPrivate->Mixer_SGFeedback[i].Target = b;
+ pPrivate->Mixer_SGFeedforward[i].Target = b;
+ }
+ }
+
+
+ /*
+ * Update the bypass mixer time constant
+ */
+ if((pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->NewParams.SourceFormat != pPrivate->CurrentParams.SourceFormat) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+ LVM_UINT16 NumChannels = 1; /* Assume MONO format */
+ LVM_INT32 Alpha;
+
+ Alpha = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_FEEDBACKMIXER_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
+ pPrivate->FeedbackMixer[0].Alpha=Alpha;
+ pPrivate->FeedbackMixer[1].Alpha=Alpha;
+ pPrivate->FeedbackMixer[2].Alpha=Alpha;
+ pPrivate->FeedbackMixer[3].Alpha=Alpha;
+
+ if (pPrivate->NewParams.SourceFormat != LVM_MONO)
+ {
+ /* Stereo or Mono-in-Stereo format data */
+ NumChannels = 2;
+ }
+ pPrivate->BypassMixer.Alpha1 = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_BYPASSMIXER_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
+ pPrivate->BypassMixer.Alpha2 = pPrivate->BypassMixer.Alpha1;
+ pPrivate->GainMixer.Alpha = pPrivate->BypassMixer.Alpha1;
+ }
+
+
+ /*
+ * Update the bypass mixer targets
+ */
+ if( (pPrivate->NewParams.Level != pPrivate->CurrentParams.Level) &&
+ (pPrivate->NewParams.OperatingMode == LVM_MODE_ON))
+ {
+ pPrivate->BypassMixer.Target2 = ((LVM_INT32)(pPrivate->NewParams.Level * 32767)/100)<<16;
+ pPrivate->BypassMixer.Target1 = LVREV_HEADROOM << 16;
+ if ((pPrivate->NewParams.Level == 0) && (pPrivate->bFirstControl == LVM_FALSE))
+ {
+ pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
+ }
+ if (pPrivate->NewParams.Level != 0)
+ {
+ pPrivate->bDisableReverb = LVM_FALSE;
+ }
+ }
+
+ if(pPrivate->NewParams.OperatingMode != pPrivate->CurrentParams.OperatingMode)
+ {
+ if(pPrivate->NewParams.OperatingMode == LVM_MODE_ON)
+ {
+ pPrivate->BypassMixer.Target2 = ((LVM_INT32)(pPrivate->NewParams.Level * 32767)/100)<<16;
+ pPrivate->BypassMixer.Target1 = LVREV_HEADROOM << 16;
+
+ pPrivate->BypassMixer.CallbackSet2 = LVM_FALSE;
+ OperatingMode = LVM_MODE_ON;
+ if (pPrivate->NewParams.Level == 0)
+ {
+ pPrivate->bDisableReverb = LVM_TRUE;
+ }
+ else
+ {
+ pPrivate->bDisableReverb = LVM_FALSE;
+ }
+ }
+ else if (pPrivate->bFirstControl == LVM_FALSE)
+ {
+ pPrivate->BypassMixer.Target2 = 0x00000000;
+ pPrivate->BypassMixer.Target1 = 0x7FFFFFFF;
+ pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
+ pPrivate->GainMixer.Target = 0x03FFFFFF;
+ OperatingMode = LVM_MODE_ON;
+ }
+ else
+ {
+ OperatingMode = LVM_MODE_OFF;
+ }
+ }
+
+
+ /*
+ * If it is the first call to ApplyNew settings force the current to the target to begin immediate playback of the effect
+ */
+ if(pPrivate->bFirstControl == LVM_TRUE)
+ {
+ pPrivate->BypassMixer.Current1 = pPrivate->BypassMixer.Target1;
+ pPrivate->BypassMixer.Current2 = pPrivate->BypassMixer.Target2;
+ }
+
+
+ /*
+ * Copy the new parameters
+ */
+ pPrivate->CurrentParams = pPrivate->NewParams;
+ pPrivate->CurrentParams.OperatingMode = OperatingMode;
+
+
+ /*
+ * Update flag
+ */
+ if(pPrivate->bFirstControl == LVM_TRUE)
+ {
+ pPrivate->bFirstControl = LVM_FALSE;
+ }
+
+
+ return LVREV_SUCCESS;
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: BypassMixer_Callback */
+/* */
+/* DESCRIPTION: */
+/* Controls the On to Off operating mode transition */
+/* */
+/* PARAMETERS: */
+/* pPrivate Pointer to the instance private parameters */
+/* */
+/* RETURNS: */
+/* LVREV_Success Succeeded */
+/* LVREV_NULLADDRESS When pPrivate is NULL */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+LVM_INT32 BypassMixer_Callback (void *pCallbackData,
+ void *pGeneralPurpose,
+ LVM_INT16 GeneralPurpose )
+{
+
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)pCallbackData;
+
+
+ /*
+ * Avoid build warnings
+ */
+ (void)pGeneralPurpose;
+ (void)GeneralPurpose;
+
+
+ /*
+ * Turn off
+ */
+ pLVREV_Private->CurrentParams.OperatingMode = LVM_MODE_OFF;
+ pLVREV_Private->bDisableReverb = LVM_TRUE;
+ LVREV_ClearAudioBuffers((LVREV_Handle_t)pCallbackData);
+
+
+ return 0;
+}
+
+/* End of file */
+
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c
new file mode 100755
index 0000000..b02b1a7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Project:: */
+/* $Author: nxp007753 $ */
+/* $Revision: 1316 $ */
+/* $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $ */
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "VectorArithmetic.h"
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_ClearAudioBuffers */
+/* */
+/* DESCRIPTION: */
+/* This function is used to clear the internal audio buffers of the module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Initialisation succeeded */
+/* LVREV_NULLADDRESS Instance is NULL */
+/* */
+/* NOTES: */
+/* 1. This function must not be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_ClearAudioBuffers(LVREV_Handle_t hInstance)
+{
+
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+
+
+ /*
+ * Check for error conditions
+ */
+ /* Check for NULL pointers */
+ if(hInstance == LVM_NULL)
+ {
+ return LVREV_NULLADDRESS;
+ }
+
+ /*
+ * Clear all filter tap data, delay-lines and other signal related data
+ */
+
+
+ LoadConst_32(0,
+ (void *)&pLVREV_Private->pFastData->HPTaps, /* Destination Cast to void: no dereferencing in function*/
+ 2);
+ LoadConst_32(0,
+ (void *)&pLVREV_Private->pFastData->LPTaps, /* Destination Cast to void: no dereferencing in function*/
+ 2);
+
+ if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+ {
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[3], 2);
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[2], 2);
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+
+ LoadConst_32(0,pLVREV_Private->pDelay_T[3], (LVM_INT16)LVREV_MAX_T3_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[2], (LVM_INT16)LVREV_MAX_T2_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+
+ }
+
+ if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_2)
+ {
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+
+ LoadConst_32(0,pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+ }
+
+ if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_1)
+ {
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+ }
+
+ return LVREV_SUCCESS;
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.c
new file mode 100755
index 0000000..ebf145e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Project:: */
+/* $Author: nxp27078 $*/
+/* $Revision: 762 $*/
+/* $Date: 2010-06-11 14:50:33 +0200 (Fri, 11 Jun 2010) $*/
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_GetControlParameters */
+/* */
+/* DESCRIPTION: */
+/* Request the LVREV module control parameters. The current parameter set is returned */
+/* via the parameter pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pControlParams Pointer to an empty parameter structure */
+/* */
+/* RETURNS: */
+/* LVREV_Success Succeeded */
+/* LVREV_NULLADDRESS When hInstance or pControlParams is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetControlParameters(LVREV_Handle_t hInstance,
+ LVREV_ControlParams_st *pControlParams)
+{
+
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+
+
+ /*
+ * Check for error conditions
+ */
+ if((hInstance == LVM_NULL) || (pControlParams == LVM_NULL))
+ {
+ return LVREV_NULLADDRESS;
+ }
+
+ /*
+ * Return the current parameters
+ */
+ *pControlParams = pLVREV_Private->NewParams;
+
+ return LVREV_SUCCESS;
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c
new file mode 100755
index 0000000..ca1c84d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Project:: */
+/* $Author: nxp007753 $ */
+/* $Revision: 1316 $ */
+/* $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $ */
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "InstAlloc.h"
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_GetInstanceHandle */
+/* */
+/* DESCRIPTION: */
+/* This function is used to create a LVREV module instance. It returns the created */
+/* instance handle through phInstance. All parameters are set to their default, */
+/* inactive state. */
+/* */
+/* PARAMETERS: */
+/* phInstance pointer to the instance handle */
+/* pMemoryTable Pointer to the memory definition table */
+/* pInstanceParams Pointer to the instance parameters */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Succeeded */
+/* LVREV_NULLADDRESS When phInstance or pMemoryTable or pInstanceParams is NULL */
+/* LVREV_NULLADDRESS When one of the memory regions has a NULL pointer */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetInstanceHandle(LVREV_Handle_t *phInstance,
+ LVREV_MemoryTable_st *pMemoryTable,
+ LVREV_InstanceParams_st *pInstanceParams)
+{
+
+ INST_ALLOC SlowData;
+ INST_ALLOC FastData;
+ INST_ALLOC FastCoef;
+ INST_ALLOC Temporary;
+ LVREV_Instance_st *pLVREV_Private;
+ LVM_INT16 i;
+ LVM_UINT16 MaxBlockSize;
+
+
+ /*
+ * Check for error conditions
+ */
+ /* Check for NULL pointers */
+ if((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pInstanceParams == LVM_NULL))
+ {
+ return LVREV_NULLADDRESS;
+ }
+ /* Check the memory table for NULL pointers */
+ for (i = 0; i < LVREV_NR_MEMORY_REGIONS; i++)
+ {
+ if (pMemoryTable->Region[i].Size!=0)
+ {
+ if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
+ {
+ return(LVREV_NULLADDRESS);
+ }
+ }
+ }
+
+ /*
+ * Check all instance parameters are in range
+ */
+ /* Check for a non-zero block size */
+ if (pInstanceParams->MaxBlockSize == 0)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ /* Check for a valid number of delay lines */
+ if ((pInstanceParams->NumDelays != LVREV_DELAYLINES_1)&&
+ (pInstanceParams->NumDelays != LVREV_DELAYLINES_2)&&
+ (pInstanceParams->NumDelays != LVREV_DELAYLINES_4))
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ /*
+ * Initialise the InstAlloc instances
+ */
+ InstAlloc_Init(&SlowData, pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress);
+ InstAlloc_Init(&FastData, pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress);
+ InstAlloc_Init(&FastCoef, pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress);
+ InstAlloc_Init(&Temporary, pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress);
+
+ /*
+ * Zero all memory regions
+ */
+ LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size)/sizeof(LVM_INT16)));
+ LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size)/sizeof(LVM_INT16)));
+ LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size)/sizeof(LVM_INT16)));
+ LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_TEMPORARY_FAST].Size)/sizeof(LVM_INT16)));
+
+ /*
+ * Set the instance handle if not already initialised
+ */
+ if (*phInstance == LVM_NULL)
+ {
+ *phInstance = InstAlloc_AddMember(&SlowData, sizeof(LVREV_Instance_st));
+ }
+ pLVREV_Private =(LVREV_Instance_st *)*phInstance;
+ pLVREV_Private->MemoryTable = *pMemoryTable;
+
+ if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_4)
+ {
+ MaxBlockSize = LVREV_MAX_AP3_DELAY;
+ }
+ else if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_2)
+ {
+ MaxBlockSize = LVREV_MAX_AP1_DELAY;
+ }
+ else
+ {
+ MaxBlockSize = LVREV_MAX_AP0_DELAY;
+ }
+
+ if(MaxBlockSize>pInstanceParams->MaxBlockSize)
+ {
+ MaxBlockSize=pInstanceParams->MaxBlockSize;
+ }
+
+
+ /*
+ * Set the data, coefficient and temporary memory pointers
+ */
+ pLVREV_Private->pFastData = InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st)); /* Fast data memory base address */
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
+ {
+ pLVREV_Private->pDelay_T[3] = InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_INT32));
+ pLVREV_Private->pDelay_T[2] = InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_INT32));
+ pLVREV_Private->pDelay_T[1] = InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
+ pLVREV_Private->pDelay_T[0] = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+
+ for( i = 0; i < 4; i++)
+ {
+ pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* Scratch for each delay line output */
+ }
+
+ LoadConst_32(0,pLVREV_Private->pDelay_T[3] ,(LVM_INT16)LVREV_MAX_T3_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[2] ,(LVM_INT16)LVREV_MAX_T2_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[1] ,(LVM_INT16)LVREV_MAX_T1_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[0] ,(LVM_INT16)LVREV_MAX_T0_DELAY);
+ }
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
+ {
+ pLVREV_Private->pDelay_T[1] = InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
+ pLVREV_Private->pDelay_T[0] = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+
+ for( i = 0; i < 2; i++)
+ {
+ pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* Scratch for each delay line output */
+ }
+
+ LoadConst_32(0,pLVREV_Private->pDelay_T[1] , (LVM_INT16)LVREV_MAX_T1_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[0] , (LVM_INT16)LVREV_MAX_T0_DELAY);
+ }
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
+ {
+ pLVREV_Private->pDelay_T[0] = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+
+ for( i = 0; i < 1; i++)
+ {
+ pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* Scratch for each delay line output */
+ }
+
+ LoadConst_32(0,pLVREV_Private->pDelay_T[0] , (LVM_INT16)LVREV_MAX_T0_DELAY);
+ }
+
+ /* All-pass delay buffer addresses and sizes */
+ pLVREV_Private->T[0] = LVREV_MAX_T0_DELAY;
+ pLVREV_Private->T[1] = LVREV_MAX_T1_DELAY;
+ pLVREV_Private->T[2] = LVREV_MAX_T2_DELAY;
+ pLVREV_Private->T[3] = LVREV_MAX_T3_DELAY;
+ pLVREV_Private->AB_Selection = 1; /* Select smoothing A to B */
+
+
+ pLVREV_Private->pFastCoef = InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st)); /* Fast coefficient memory base address */
+ pLVREV_Private->pScratch = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* General purpose scratch */
+ pLVREV_Private->pInputSave = InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_INT32) * MaxBlockSize); /* Mono->stereo input save for end mix */
+ LoadConst_32(0, pLVREV_Private->pInputSave, (LVM_INT16)(MaxBlockSize*2));
+
+
+ /*
+ * Save the instance parameters in the instance structure
+ */
+ pLVREV_Private->InstanceParams = *pInstanceParams;
+
+
+ /*
+ * Set the parameters to invalid
+ */
+ pLVREV_Private->CurrentParams.SampleRate = LVM_FS_INVALID;
+ pLVREV_Private->CurrentParams.OperatingMode = LVM_MODE_DUMMY;
+ pLVREV_Private->CurrentParams.SourceFormat = LVM_SOURCE_DUMMY;
+
+ pLVREV_Private->bControlPending = LVM_FALSE;
+ pLVREV_Private->bFirstControl = LVM_TRUE;
+ pLVREV_Private->bDisableReverb = LVM_FALSE;
+
+
+ /*
+ * Set mixer parameters
+ */
+ pLVREV_Private->BypassMixer.CallbackParam2 = 0;
+ pLVREV_Private->BypassMixer.pCallbackHandle2 = pLVREV_Private;
+ pLVREV_Private->BypassMixer.pGeneralPurpose2 = LVM_NULL;
+ pLVREV_Private->BypassMixer.pCallBack2 = BypassMixer_Callback;
+ pLVREV_Private->BypassMixer.CallbackSet2 = LVM_FALSE;
+ pLVREV_Private->BypassMixer.Current2 = 0;
+ pLVREV_Private->BypassMixer.Target2 = 0;
+ pLVREV_Private->BypassMixer.CallbackParam1 = 0;
+ pLVREV_Private->BypassMixer.pCallbackHandle1 = LVM_NULL;
+ pLVREV_Private->BypassMixer.pGeneralPurpose1 = LVM_NULL;
+ pLVREV_Private->BypassMixer.pCallBack1 = LVM_NULL;
+ pLVREV_Private->BypassMixer.CallbackSet1 = LVM_FALSE;
+ pLVREV_Private->BypassMixer.Current1 = 0x7fffffff;
+ pLVREV_Private->BypassMixer.Target1 = 0x7fffffff;
+
+ pLVREV_Private->RoomSizeInms = 100; // 100 msec
+
+
+ /*
+ * Set the output gain mixer parameters
+ */
+ pLVREV_Private->GainMixer.CallbackParam = 0;
+ pLVREV_Private->GainMixer.pCallbackHandle = LVM_NULL;
+ pLVREV_Private->GainMixer.pGeneralPurpose = LVM_NULL;
+ pLVREV_Private->GainMixer.pCallBack = LVM_NULL;
+ pLVREV_Private->GainMixer.CallbackSet = LVM_FALSE;
+ pLVREV_Private->GainMixer.Current = 0x03ffffff;
+ pLVREV_Private->GainMixer.Target = 0x03ffffff;
+
+
+ /*
+ * Set the All-Pass Filter mixers
+ */
+ for (i=0; i<4; i++)
+ {
+ pLVREV_Private->pOffsetA[i] = pLVREV_Private->pDelay_T[i];
+ pLVREV_Private->pOffsetB[i] = pLVREV_Private->pDelay_T[i];
+ /* Delay tap selection mixer */
+ pLVREV_Private->Mixer_APTaps[i].CallbackParam2 = 0;
+ pLVREV_Private->Mixer_APTaps[i].pCallbackHandle2 = LVM_NULL;
+ pLVREV_Private->Mixer_APTaps[i].pGeneralPurpose2 = LVM_NULL;
+ pLVREV_Private->Mixer_APTaps[i].pCallBack2 = LVM_NULL;
+ pLVREV_Private->Mixer_APTaps[i].CallbackSet2 = LVM_FALSE;
+ pLVREV_Private->Mixer_APTaps[i].Current2 = 0;
+ pLVREV_Private->Mixer_APTaps[i].Target2 = 0;
+ pLVREV_Private->Mixer_APTaps[i].CallbackParam1 = 0;
+ pLVREV_Private->Mixer_APTaps[i].pCallbackHandle1 = LVM_NULL;
+ pLVREV_Private->Mixer_APTaps[i].pGeneralPurpose1 = LVM_NULL;
+ pLVREV_Private->Mixer_APTaps[i].pCallBack1 = LVM_NULL;
+ pLVREV_Private->Mixer_APTaps[i].CallbackSet1 = LVM_FALSE;
+ pLVREV_Private->Mixer_APTaps[i].Current1 = 0;
+ pLVREV_Private->Mixer_APTaps[i].Target1 = 0x7fffffff;
+ /* Feedforward mixer */
+ pLVREV_Private->Mixer_SGFeedforward[i].CallbackParam = 0;
+ pLVREV_Private->Mixer_SGFeedforward[i].pCallbackHandle = LVM_NULL;
+ pLVREV_Private->Mixer_SGFeedforward[i].pGeneralPurpose = LVM_NULL;
+ pLVREV_Private->Mixer_SGFeedforward[i].pCallBack = LVM_NULL;
+ pLVREV_Private->Mixer_SGFeedforward[i].CallbackSet = LVM_FALSE;
+ pLVREV_Private->Mixer_SGFeedforward[i].Current = 0;
+ pLVREV_Private->Mixer_SGFeedforward[i].Target = 0;
+ /* Feedback mixer */
+ pLVREV_Private->Mixer_SGFeedback[i].CallbackParam = 0;
+ pLVREV_Private->Mixer_SGFeedback[i].pCallbackHandle = LVM_NULL;
+ pLVREV_Private->Mixer_SGFeedback[i].pGeneralPurpose = LVM_NULL;
+ pLVREV_Private->Mixer_SGFeedback[i].pCallBack = LVM_NULL;
+ pLVREV_Private->Mixer_SGFeedback[i].CallbackSet = LVM_FALSE;
+ pLVREV_Private->Mixer_SGFeedback[i].Current = 0;
+ pLVREV_Private->Mixer_SGFeedback[i].Target = 0;
+ /* Feedback gain mixer */
+ pLVREV_Private->FeedbackMixer[i].CallbackParam = 0;
+ pLVREV_Private->FeedbackMixer[i].pCallbackHandle = LVM_NULL;
+ pLVREV_Private->FeedbackMixer[i].pGeneralPurpose = LVM_NULL;
+ pLVREV_Private->FeedbackMixer[i].pCallBack = LVM_NULL;
+ pLVREV_Private->FeedbackMixer[i].CallbackSet = LVM_FALSE;
+ pLVREV_Private->FeedbackMixer[i].Current = 0;
+ pLVREV_Private->FeedbackMixer[i].Target = 0;
+ }
+ /* Delay tap index */
+ pLVREV_Private->A_DelaySize[0] = LVREV_MAX_AP0_DELAY;
+ pLVREV_Private->B_DelaySize[0] = LVREV_MAX_AP0_DELAY;
+ pLVREV_Private->A_DelaySize[1] = LVREV_MAX_AP1_DELAY;
+ pLVREV_Private->B_DelaySize[1] = LVREV_MAX_AP1_DELAY;
+ pLVREV_Private->A_DelaySize[2] = LVREV_MAX_AP2_DELAY;
+ pLVREV_Private->B_DelaySize[2] = LVREV_MAX_AP2_DELAY;
+ pLVREV_Private->A_DelaySize[3] = LVREV_MAX_AP3_DELAY;
+ pLVREV_Private->B_DelaySize[3] = LVREV_MAX_AP3_DELAY;
+
+
+ LVREV_ClearAudioBuffers(*phInstance);
+
+ return LVREV_SUCCESS;
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c
new file mode 100755
index 0000000..e16a3d3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1007 $*/
+/* $Date: 2010-06-28 14:06:36 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "InstAlloc.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_GetMemoryTable */
+/* */
+/* DESCRIPTION: */
+/* This function is used for memory allocation and free. It can be called in */
+/* two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and allocated */
+/* base addresses. */
+/* */
+/* When this function is called for memory allocation (hInstance=NULL) the memory */
+/* base address pointers are NULL on return. */
+/* */
+/* When the function is called for free (hInstance = Instance Handle) the memory */
+/* table returns the allocated memory and base addresses used during initialisation. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pMemoryTable Pointer to an empty memory table */
+/* pInstanceParams Pointer to the instance parameters */
+/* */
+/* RETURNS: */
+/* LVREV_Success Succeeded */
+/* LVREV_NULLADDRESS When pMemoryTable is NULL */
+/* LVREV_NULLADDRESS When requesting memory requirements and pInstanceParams */
+/* is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetMemoryTable(LVREV_Handle_t hInstance,
+ LVREV_MemoryTable_st *pMemoryTable,
+ LVREV_InstanceParams_st *pInstanceParams)
+{
+
+ INST_ALLOC SlowData;
+ INST_ALLOC FastData;
+ INST_ALLOC FastCoef;
+ INST_ALLOC Temporary;
+ LVM_INT16 i;
+ LVM_UINT16 MaxBlockSize;
+
+
+ /*
+ * Check for error conditions
+ */
+ /* Check for NULL pointer */
+ if (pMemoryTable == LVM_NULL)
+ {
+ return(LVREV_NULLADDRESS);
+ }
+
+ /*
+ * Check all instance parameters are in range
+ */
+ if (pInstanceParams != LVM_NULL)
+ {
+ /*
+ * Call for memory allocation, so check the parameters
+ */
+ /* Check for a non-zero block size */
+ if (pInstanceParams->MaxBlockSize == 0)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ /* Check for a valid number of delay lines */
+ if ((pInstanceParams->NumDelays != LVREV_DELAYLINES_1) &&
+ (pInstanceParams->NumDelays != LVREV_DELAYLINES_2) &&
+ (pInstanceParams->NumDelays != LVREV_DELAYLINES_4))
+ {
+ return LVREV_OUTOFRANGE;
+ }
+ }
+
+ /*
+ * Initialise the InstAlloc instances
+ */
+ InstAlloc_Init(&SlowData, (void *)LVM_NULL);
+ InstAlloc_Init(&FastData, (void *)LVM_NULL);
+ InstAlloc_Init(&FastCoef, (void *)LVM_NULL);
+ InstAlloc_Init(&Temporary, (void *)LVM_NULL);
+
+
+ /*
+ * Fill in the memory table
+ */
+ if (hInstance == LVM_NULL)
+ {
+ /*
+ * Check for null pointers
+ */
+ if (pInstanceParams == LVM_NULL)
+ {
+ return(LVREV_NULLADDRESS);
+ }
+
+
+ /*
+ * Select the maximum internal block size
+ */
+ if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_4)
+ {
+ MaxBlockSize = LVREV_MAX_AP3_DELAY;
+ }
+ else if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_2)
+ {
+ MaxBlockSize = LVREV_MAX_AP1_DELAY;
+ }
+ else
+ {
+ MaxBlockSize = LVREV_MAX_AP0_DELAY;
+ }
+
+ if(MaxBlockSize>pInstanceParams->MaxBlockSize)
+ {
+ MaxBlockSize=pInstanceParams->MaxBlockSize;
+ }
+
+
+ /*
+ * Slow data memory
+ */
+ InstAlloc_AddMember(&SlowData, sizeof(LVREV_Instance_st));
+ pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size = InstAlloc_GetTotal(&SlowData);
+ pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Type = LVM_PERSISTENT_SLOW_DATA;
+ pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
+
+
+ /*
+ * Persistent fast data memory
+ */
+ InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
+ {
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_INT32));
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_INT32));
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+ }
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
+ {
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+ }
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
+ {
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+ }
+
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size = InstAlloc_GetTotal(&FastData);
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Type = LVM_PERSISTENT_FAST_DATA;
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
+
+
+ /*
+ * Persistent fast coefficient memory
+ */
+ InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size = InstAlloc_GetTotal(&FastCoef);
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type = LVM_PERSISTENT_FAST_COEF;
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
+
+
+ /*
+ * Temporary fast memory
+ */
+ InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* General purpose scratch memory */
+ InstAlloc_AddMember(&Temporary, 2*sizeof(LVM_INT32) * MaxBlockSize); /* Mono->stereo input saved for end mix */
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
+ {
+ for(i=0; i<4; i++)
+ {
+ InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* A Scratch buffer for each delay line */
+ }
+ }
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
+ {
+ for(i=0; i<2; i++)
+ {
+ InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* A Scratch buffer for each delay line */
+ }
+ }
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
+ {
+ for(i=0; i<1; i++)
+ {
+ InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* A Scratch buffer for each delay line */
+ }
+ }
+
+ pMemoryTable->Region[LVM_TEMPORARY_FAST].Size = InstAlloc_GetTotal(&Temporary);
+ pMemoryTable->Region[LVM_TEMPORARY_FAST].Type = LVM_TEMPORARY_FAST;
+ pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
+
+ }
+ else
+ {
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+
+
+ /*
+ * Read back memory allocation table
+ */
+ *pMemoryTable = pLVREV_Private->MemoryTable;
+ }
+
+
+ return(LVREV_SUCCESS);
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
new file mode 100755
index 0000000..896b051
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Project:: */
+/* $Author: nxp007753 $ */
+/* $Revision: 1316 $ */
+/* $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $ */
+/* */
+/****************************************************************************************/
+
+#ifndef __LVREV_PRIVATE_H__
+#define __LVREV_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV.h"
+#include "LVREV_Tables.h"
+#include "BIQUAD.h"
+#include "Filter.h"
+#include "VectorArithmetic.h"
+#include "Mixer.h"
+#include "LVM_Macros.h"
+
+
+/****************************************************************************************/
+/* */
+/* Defines */
+/* */
+/****************************************************************************************/
+/* General */
+#define ONE_OVER_SQRT_TWO 23170 /* 1/sqrt(2) * 2^15 */
+#define LVREV_B_8_on_1000 17179869 /* 0.8 * 2^31 */
+#define LVREV_HEADROOM 8192 /* -12dB * 2^15 */
+#define LVREV_2_9_INQ29 1583769190L /* 2.9 in Q29 format */
+#define LVREV_MIN3DB 0x5A82 /* -3dB in Q15 format */
+
+/* Intenal constants */
+#define LVREV_LP_Poly_Order 4
+#define LVREV_LP_Poly_Shift 5
+#define LVREV_T_3_Power_0_on_4 32768
+#define LVREV_T_3_Power_1_on_4 43125
+#define LVREV_T_3_Power_2_on_4 56755
+#define LVREV_T_3_Power_3_on_4 74694
+#define LVREV_T60_SCALE 306774 /*(32767/7000)<<16 */
+#define LVREV_T_3_Power_minus0_on_4 32767 /* 3^(-0/4) * 2^15 */
+#define LVREV_T_3_Power_minus1_on_4 24898 /* 3^(-1/4) * 2^15 */
+#define LVREV_T_3_Power_minus2_on_4 18919 /* 3^(-2/4) * 2^15 */
+#define LVREV_T_3_Power_minus3_on_4 14375 /* 3^(-3/4) * 2^15 */
+#define LVREV_MAX_T3_DELAY 2527 /* ((48000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T2_DELAY 3326 /* ((48000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T1_DELAY 4377 /* ((48000 * 120 * LVREV_T_3_Power_minus1_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T0_DELAY 5760 /* ((48000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1000 */
+#define LVREV_MAX_AP3_DELAY 1685 /* ((48000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP2_DELAY 2218 /* ((48000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP1_DELAY 2918 /* ((48000 * 120 * LVREV_T_3_Power_minus1_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP0_DELAY 3840 /* ((48000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1500 */
+#define LVREV_BYPASSMIXER_TC 1000 /* Bypass mixer time constant*/
+#define LVREV_ALLPASS_TC 1000 /* All-pass filter time constant */
+#define LVREV_ALLPASS_TAP_TC 10000 /* All-pass filter dely tap change */
+#define LVREV_FEEDBACKMIXER_TC 100 /* Feedback mixer time constant*/
+#define LVREV_OUTPUTGAIN_SHIFT 5 /* Bits shift for output gain correction */
+
+/* Parameter limits */
+#define LVREV_NUM_FS 9 /* Number of supported sample rates */
+#define LVREV_MAXBLKSIZE_LIMIT 64 /* Maximum block size low limit */
+#define LVREV_MAX_LEVEL 100 /* Maximum level, 100% */
+#define LVREV_MIN_LPF_CORNER 50 /* Low pass filter limits */
+#define LVREV_MAX_LPF_CORNER 23999
+#define LVREV_MIN_HPF_CORNER 20 /* High pass filrer limits */
+#define LVREV_MAX_HPF_CORNER 1000
+#define LVREV_MAX_T60 7000 /* Maximum T60 time in ms */
+#define LVREV_MAX_DENSITY 100 /* Maximum density, 100% */
+#define LVREV_MAX_DAMPING 100 /* Maximum damping, 100% */
+#define LVREV_MAX_ROOMSIZE 100 /* Maximum room size, 100% */
+
+
+
+/****************************************************************************************/
+/* */
+/* Structures */
+/* */
+/****************************************************************************************/
+/* Fast data structure */
+typedef struct
+{
+
+ Biquad_1I_Order1_Taps_t HPTaps; /* High pass filter taps */
+ Biquad_1I_Order1_Taps_t LPTaps; /* Low pass filter taps */
+ Biquad_1I_Order1_Taps_t RevLPTaps[4]; /* Reverb low pass filters taps */
+
+} LVREV_FastData_st;
+
+
+/* Fast coefficient structure */
+typedef struct
+{
+
+ Biquad_Instance_t HPCoefs; /* High pass filter coefficients */
+ Biquad_Instance_t LPCoefs; /* Low pass filter coefficients */
+ Biquad_Instance_t RevLPCoefs[4]; /* Reverb low pass filters coefficients */
+
+} LVREV_FastCoef_st;
+
+
+/* Instance parameter structure */
+typedef struct
+{
+ /* General */
+ LVREV_InstanceParams_st InstanceParams; /* Initialisation time instance parameters */
+ LVREV_MemoryTable_st MemoryTable; /* Memory table */
+ LVREV_ControlParams_st CurrentParams; /* Parameters being used */
+ LVREV_ControlParams_st NewParams; /* New parameters from the calling application */
+ LVM_CHAR bControlPending; /* Flag to indicate new parameters are available */
+ LVM_CHAR bFirstControl; /* Flag to indicate that the control function is called for the first time */
+ LVM_CHAR bDisableReverb; /* Flag to indicate that the mix level is 0% and the reverb can be disabled */
+ LVM_INT32 RoomSizeInms; /* Room size in msec */
+ LVM_INT32 MaxBlkLen; /* Maximum block size for internal processing */
+
+ /* Aligned memory pointers */
+ LVREV_FastData_st *pFastData; /* Fast data memory base address */
+ LVREV_FastCoef_st *pFastCoef; /* Fast coefficient memory base address */
+ LVM_INT32 *pScratchDelayLine[4]; /* Delay line scratch memory */
+ LVM_INT32 *pScratch; /* Multi ussge scratch */
+ LVM_INT32 *pInputSave; /* Reverb block input save for dry/wet mixing*/
+
+ /* Feedback matrix */
+ Mix_1St_Cll_t FeedbackMixer[4]; /* Mixer for Pop and Click Supression caused by feedback Gain */
+
+ /* All-Pass Filter */
+ LVM_INT32 T[4]; /* Maximum delay size of buffer */
+ LVM_INT32 *pDelay_T[4]; /* Pointer to delay buffers */
+ LVM_INT32 Delay_AP[4]; /* Offset to AP delay buffer start */
+ LVM_INT16 AB_Selection; /* Smooth from tap A to B when 1 otherwise B to A */
+ LVM_INT32 A_DelaySize[4]; /* A delay length in samples */
+ LVM_INT32 B_DelaySize[4]; /* B delay length in samples */
+ LVM_INT32 *pOffsetA[4]; /* Offset for the A delay tap */
+ LVM_INT32 *pOffsetB[4]; /* Offset for the B delay tap */
+ Mix_2St_Cll_t Mixer_APTaps[4]; /* Smoothed AP delay mixer */
+ Mix_1St_Cll_t Mixer_SGFeedback[4]; /* Smoothed SAfeedback gain */
+ Mix_1St_Cll_t Mixer_SGFeedforward[4]; /* Smoothed AP feedforward gain */
+
+ /* Output gain */
+ Mix_2St_Cll_t BypassMixer; /* Dry/wet mixer */
+ LVM_INT16 Gain; /* Gain applied to output to maintain average signal power */
+ Mix_1St_Cll_t GainMixer; /* Gain smoothing */
+
+} LVREV_Instance_st;
+
+
+/****************************************************************************************/
+/* */
+/* Function prototypes */
+/* */
+/****************************************************************************************/
+
+LVREV_ReturnStatus_en LVREV_ApplyNewSettings(LVREV_Instance_st *pPrivate);
+
+void ReverbBlock(LVM_INT32 *pInput,
+ LVM_INT32 *pOutput,
+ LVREV_Instance_st *pPrivate,
+ LVM_UINT16 NumSamples);
+
+LVM_INT32 BypassMixer_Callback(void *pCallbackData,
+ void *pGeneralPurpose,
+ LVM_INT16 GeneralPurpose );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** __LVREV_PRIVATE_H__ **/
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
new file mode 100755
index 0000000..822ac8f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
@@ -0,0 +1,550 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Project:: */
+/* $Author: nxp007753 $ */
+/* $Revision: 1316 $ */
+/* $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $ */
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "VectorArithmetic.h"
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the LVREV module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* */
+/* RETURNS: */
+/* LVREV_Success Succeeded */
+/* LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size */
+/* LVREV_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */
+/* */
+/* NOTES: */
+/* 1. The input and output buffers must be 32-bit aligned */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t hInstance,
+ const LVM_INT32 *pInData,
+ LVM_INT32 *pOutData,
+ const LVM_UINT16 NumSamples)
+{
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+ LVM_INT32 *pInput = (LVM_INT32 *)pInData;
+ LVM_INT32 *pOutput = pOutData;
+ LVM_INT32 SamplesToProcess, RemainingSamples, format;
+
+ /*
+ * Check for error conditions
+ */
+
+ /* Check for NULL pointers */
+ if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
+ {
+ return LVREV_NULLADDRESS;
+ }
+
+
+ /*
+ * Apply the new controls settings if required
+ */
+ if(pLVREV_Private->bControlPending == LVM_TRUE)
+ {
+ LVREV_ReturnStatus_en errorCode;
+
+ /*
+ * Clear the pending flag and update the control settings
+ */
+ pLVREV_Private->bControlPending = LVM_FALSE;
+
+ errorCode = LVREV_ApplyNewSettings (pLVREV_Private);
+
+ if(errorCode != LVREV_SUCCESS)
+ {
+ return errorCode;
+ }
+ }
+
+ /*
+ * Trap the case where the number of samples is zero.
+ */
+ if (NumSamples == 0)
+ {
+ return LVREV_SUCCESS;
+ }
+
+ RemainingSamples = (LVM_INT32)NumSamples;
+
+ format = 1;
+ if (pLVREV_Private->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ format = 2;
+ }
+
+ while (RemainingSamples!=0)
+ {
+ /*
+ * If OFF copy and reformat the data as necessary
+ */
+ if (pLVREV_Private->CurrentParams.OperatingMode == LVM_MODE_OFF)
+ {
+ if((pInput != pOutput) || (pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO))
+ {
+ /*
+ * Copy the data to the output buffer
+ */
+
+ if (pLVREV_Private->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ RemainingSamples = (RemainingSamples << 1); /* Stereo data */
+ }
+
+ Copy_16((LVM_INT16 *)pInput,
+ (LVM_INT16 *)pOutput,
+ (LVM_INT16)(RemainingSamples << 1));
+ }
+
+ RemainingSamples = 0;
+ }
+
+ /*
+ * Process the data
+ */
+ else
+ {
+
+ if(RemainingSamples > pLVREV_Private->MaxBlkLen)
+ {
+ SamplesToProcess = pLVREV_Private->MaxBlkLen;
+ RemainingSamples = (LVM_INT16)(RemainingSamples - SamplesToProcess);
+ }
+ else
+ {
+ SamplesToProcess = RemainingSamples;
+ RemainingSamples = 0;
+ }
+
+ ReverbBlock(pInput, pOutput, pLVREV_Private, (LVM_UINT16)SamplesToProcess);
+
+ pInput = (LVM_INT32 *)(pInput +(SamplesToProcess*format));
+ pOutput = (LVM_INT32 *)(pOutput+(SamplesToProcess*format));
+ }
+ }
+
+ return LVREV_SUCCESS;
+}
+
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: ReverbBlock */
+/* */
+/* DESCRIPTION: */
+/* Process function for the LVREV module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* */
+/* RETURNS: */
+/* LVREV_Success Succeeded */
+/* LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size */
+/* LVREV_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */
+/* */
+/* NOTES: */
+/* 1. The input and output buffers must be 32-bit aligned */
+/* */
+/****************************************************************************************/
+
+void ReverbBlock(LVM_INT32 *pInput, LVM_INT32 *pOutput, LVREV_Instance_st *pPrivate, LVM_UINT16 NumSamples)
+{
+ LVM_INT16 j, size;
+ LVM_INT32 *pDelayLine;
+ LVM_INT32 *pDelayLineInput = pPrivate->pScratch;
+ LVM_INT32 *pScratch = pPrivate->pScratch;
+ LVM_INT32 *pIn;
+ LVM_INT32 *pTemp = pPrivate->pInputSave;
+ LVM_INT32 NumberOfDelayLines;
+
+ /******************************************************************************
+ * All calculations will go into the buffer pointed to by pTemp, this will *
+ * then be mixed with the original input to create the final output. *
+ * *
+ * When INPLACE processing is selected this must be a temporary buffer and *
+ * hence this is the worst case, so for simplicity this will ALWAYS be so *
+ * *
+ * The input buffer will remain untouched until the output of the mixer if *
+ * INPLACE processing is selected. *
+ * *
+ * The temp buffer will always be NumSamples in size regardless of MONO or *
+ * STEREO input. In the case of stereo input all processing is done in MONO *
+ * and the final output is converted to STEREO after the mixer *
+ ******************************************************************************/
+
+ if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4 )
+ {
+ NumberOfDelayLines = 4;
+ }
+ else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2 )
+ {
+ NumberOfDelayLines = 2;
+ }
+ else
+ {
+ NumberOfDelayLines = 1;
+ }
+
+ if(pPrivate->CurrentParams.SourceFormat == LVM_MONO)
+ {
+ pIn = pInput;
+ }
+ else
+ {
+ /*
+ * Stereo to mono conversion
+ */
+
+ From2iToMono_32( pInput,
+ pTemp,
+ (LVM_INT16)NumSamples);
+
+ pIn = pTemp;
+ }
+
+ Mult3s_32x16(pIn,
+ (LVM_INT16)LVREV_HEADROOM,
+ pTemp,
+ (LVM_INT16)NumSamples);
+
+ /*
+ * High pass filter
+ */
+ FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->HPCoefs,
+ pTemp,
+ pTemp,
+ (LVM_INT16)NumSamples);
+ /*
+ * Low pass filter
+ */
+ FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->LPCoefs,
+ pTemp,
+ pTemp,
+ (LVM_INT16)NumSamples);
+
+ /*
+ * Process all delay lines
+ */
+
+ for(j = 0; j < NumberOfDelayLines; j++)
+ {
+ pDelayLine = pPrivate->pScratchDelayLine[j];
+
+ /*
+ * All-pass filter with pop and click suppression
+ */
+ /* Get the smoothed, delayed output. Put it in the output buffer */
+ MixSoft_2St_D32C31_SAT(&pPrivate->Mixer_APTaps[j],
+ pPrivate->pOffsetA[j],
+ pPrivate->pOffsetB[j],
+ pDelayLine,
+ (LVM_INT16)NumSamples);
+ /* Re-align the all pass filter delay buffer and copying the fixed delay data to the AP delay in the process */
+ Copy_16((LVM_INT16 *)&pPrivate->pDelay_T[j][NumSamples],
+ (LVM_INT16 *)pPrivate->pDelay_T[j],
+ (LVM_INT16)((pPrivate->T[j]-NumSamples) << 1)); /* 32-bit data */
+ /* Apply the smoothed feedback and save to fixed delay input (currently empty) */
+ MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedback[j],
+ pDelayLine,
+ &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ (LVM_INT16)NumSamples);
+ /* Sum into the AP delay line */
+ Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ -0x7fff, /* Invert since the feedback coefficient is negative */
+ &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples],
+ (LVM_INT16)NumSamples);
+ /* Apply smoothed feedforward sand save to fixed delay input (currently empty) */
+ MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedforward[j],
+ &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples],
+ &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ (LVM_INT16)NumSamples);
+ /* Sum into the AP output */
+ Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ 0x7fff,
+ pDelayLine,
+ (LVM_INT16)NumSamples);
+
+ /*
+ * Feedback gain
+ */
+ MixSoft_1St_D32C31_WRA(&pPrivate->FeedbackMixer[j], pDelayLine, pDelayLine, NumSamples);
+
+ /*
+ * Low pass filter
+ */
+ FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->RevLPCoefs[j],
+ pDelayLine,
+ pDelayLine,
+ (LVM_INT16)NumSamples);
+ }
+
+ /*
+ * Apply rotation matrix and delay samples
+ */
+ for(j = 0; j < NumberOfDelayLines; j++)
+ {
+
+ Copy_16( (LVM_INT16*)(pTemp),
+ (LVM_INT16*)(pDelayLineInput),
+ (LVM_INT16)(NumSamples << 1));
+
+ /*
+ * Rotation matrix mix
+ */
+ switch(j)
+ {
+ case 3:
+ /*
+ * Add delay line 1 and 2 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[2], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+
+ break;
+ case 2:
+
+ /*
+ * Add delay line 0 and 3 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[3], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+
+ break;
+ case 1:
+ if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+ {
+ /*
+ * Add delay line 0 and 3 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[3], pDelayLineInput, (LVM_INT16)NumSamples);
+
+ }
+ else
+ {
+ /*
+ * Add delay line 0 and 1 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+
+ }
+ break;
+ case 0:
+ if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+ {
+ /*
+ * Add delay line 1 and 2 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[2], pDelayLineInput, (LVM_INT16)NumSamples);
+
+ }
+ else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
+ {
+ /*
+ * Add delay line 0 and 1 contribution
+ */
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples);
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+
+ }
+ else
+ {
+ /*
+ * Add delay line 0 contribution
+ */
+
+ /* SOURCE DESTINATION*/
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Delay samples
+ */
+ Copy_16((LVM_INT16 *)pDelayLineInput,
+ (LVM_INT16 *)&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ (LVM_INT16)(NumSamples << 1)); /* 32-bit data */
+
+ }
+
+
+ /*
+ * Create stereo output
+ */
+ switch(pPrivate->InstanceParams.NumDelays)
+ {
+ case LVREV_DELAYLINES_4:
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[3],
+ pPrivate->pScratchDelayLine[0],
+ (LVM_INT16)NumSamples);
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[2],
+ pPrivate->pScratchDelayLine[1],
+ (LVM_INT16)NumSamples);
+
+ if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
+ pPrivate->pScratchDelayLine[1],
+ pTemp,
+ (LVM_INT16)NumSamples);
+
+ }
+ else
+ {
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[1],
+ pPrivate->pScratchDelayLine[0],
+ (LVM_INT16)NumSamples);
+
+ /*Apply 3-dB gain in-order to compensate for the gain change in stereo mode*/
+ Mult3s_32x16(pPrivate->pScratchDelayLine[0],
+ LVREV_MIN3DB,
+ pTemp,
+ (LVM_INT16)NumSamples);
+ }
+ break;
+ case LVREV_DELAYLINES_2:
+
+ Copy_16( (LVM_INT16*)pPrivate->pScratchDelayLine[1],
+ (LVM_INT16*)pScratch,
+ (LVM_INT16)(NumSamples << 1));
+
+
+
+ if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
+ {
+
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0],
+ -0x8000,
+ pScratch,
+ (LVM_INT16)NumSamples);
+ }
+
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[1],
+ pPrivate->pScratchDelayLine[0],
+ (LVM_INT16)NumSamples);
+
+
+ if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
+ pScratch,
+ pTemp,
+ (LVM_INT16)NumSamples);
+ }
+ else
+ {
+ Copy_16( (LVM_INT16*)pPrivate->pScratchDelayLine[0],
+ (LVM_INT16*)pTemp,
+ (LVM_INT16)(NumSamples << 1));
+
+ }
+ break;
+ case LVREV_DELAYLINES_1:
+ if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
+ {
+
+ MonoTo2I_32(pPrivate->pScratchDelayLine[0],
+ pTemp,
+ (LVM_INT16)NumSamples);
+ }
+ else
+ {
+ pTemp = pPrivate->pScratchDelayLine[0];
+ }
+ break;
+ default:
+ break;
+ }
+
+
+ /*
+ * Dry/wet mixer
+ */
+ if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ size = (LVM_INT16)(NumSamples << 1);
+ }
+ else
+ {
+ size = (LVM_INT16)NumSamples;
+ }
+
+ MixSoft_2St_D32C31_SAT(&pPrivate->BypassMixer,
+ pInput,
+ pTemp,
+ pOutput,
+ size);
+
+ /* Apply Gain*/
+ if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ size = (LVM_INT16)(NumSamples << 1);
+ }
+ else
+ {
+ size = (LVM_INT16)NumSamples;
+ }
+
+ Shift_Sat_v32xv32 (LVREV_OUTPUTGAIN_SHIFT,
+ pOutput,
+ pOutput,
+ size);
+
+ MixSoft_1St_D32C31_WRA(&pPrivate->GainMixer,
+ pOutput,
+ pOutput,
+ size);
+ return;
+}
+
+
+/* End of file */
+
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
new file mode 100755
index 0000000..124fd3b
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Project:: */
+/* $Author: nxp007753 $ */
+/* $Revision: 1316 $ */
+/* $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $ */
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_SetControlParameters */
+/* */
+/* DESCRIPTION: */
+/* Sets or changes the LVREV module parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pNewParams Pointer to a parameter structure */
+/* */
+/* RETURNS: */
+/* LVM_Success Succeeded */
+/* LVREV_NULLADDRESS When hInstance or pNewParams is NULL */
+/* LVREV_OUTOFRANGE When any of the new parameters is out of range */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_SetControlParameters(LVREV_Handle_t hInstance,
+ LVREV_ControlParams_st *pNewParams)
+{
+
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+
+
+ /*
+ * Check for error conditions
+ */
+ if((hInstance == LVM_NULL) || (pNewParams == LVM_NULL))
+ {
+ return LVREV_NULLADDRESS;
+ }
+
+ /*
+ * Check all new control parameters are in range
+ */
+ if( ((pNewParams->OperatingMode != LVM_MODE_OFF) && (pNewParams->OperatingMode != LVM_MODE_ON)) ||
+ ((pNewParams->SampleRate != LVM_FS_8000) && (pNewParams->SampleRate != LVM_FS_11025) && (pNewParams->SampleRate != LVM_FS_12000) &&
+ (pNewParams->SampleRate != LVM_FS_16000) && (pNewParams->SampleRate != LVM_FS_22050) && (pNewParams->SampleRate != LVM_FS_24000) &&
+ (pNewParams->SampleRate != LVM_FS_32000) && (pNewParams->SampleRate != LVM_FS_44100) && (pNewParams->SampleRate != LVM_FS_48000)) ||
+ ((pNewParams->SourceFormat != LVM_STEREO) && (pNewParams->SourceFormat != LVM_MONOINSTEREO) && (pNewParams->SourceFormat != LVM_MONO)) )
+ {
+ return (LVREV_OUTOFRANGE);
+ }
+
+
+ if (pNewParams->Level > LVREV_MAX_LEVEL)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ if ((pNewParams->LPF < LVREV_MIN_LPF_CORNER) || (pNewParams->LPF > LVREV_MAX_LPF_CORNER))
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ if ((pNewParams->HPF < LVREV_MIN_HPF_CORNER) || (pNewParams->HPF > LVREV_MAX_HPF_CORNER))
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ if (pNewParams->T60 > LVREV_MAX_T60)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ if (pNewParams->Density > LVREV_MAX_DENSITY)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ if (pNewParams->Damping > LVREV_MAX_DAMPING)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ if (pNewParams->RoomSize > LVREV_MAX_ROOMSIZE)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+
+
+ /*
+ * Copy the new parameters and set the flag to indicate they are available
+ */
+ pLVREV_Private->NewParams = *pNewParams;
+ pLVREV_Private->bControlPending = LVM_TRUE;
+
+ return LVREV_SUCCESS;
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c
new file mode 100755
index 0000000..9249a31
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $ */
+/* $Revision: 1011 $ */
+/* $Date: 2010-06-28 15:07:08 +0200 (Mon, 28 Jun 2010) $ */
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV.h"
+
+/****************************************************************************************/
+/* */
+/* Tables */
+/* */
+/****************************************************************************************/
+
+/* Table with supported sampling rates. The table can be indexed using LVM_Fs_en */
+const LVM_UINT16 LVM_FsTable[] = {
+ 8000 ,
+ 11025,
+ 12000,
+ 16000,
+ 22050,
+ 24000,
+ 32000,
+ 44100,
+ 48000
+};
+
+/* Table with supported sampling rates. The table can be indexed using LVM_Fs_en */
+LVM_UINT16 LVM_GetFsFromTable(LVM_Fs_en FsIndex){
+ if (FsIndex > LVM_FS_48000)
+ return 0;
+
+ return (LVM_FsTable[FsIndex]);
+}
+
+/* In order to maintain consistant input and out put signal strengths
+ output gain/attenuation is applied. This gain depends on T60 and Rooms
+ size parameters. These polynomial coefficients are calculated experimentally.
+ First value in the table is room size
+ second value is A0
+ third value is A1
+ fourth value is A2
+ fifth value is A3
+ sixth value is A4
+
+ shift value is to be added array (to use LVM_Polynomial function)
+
+ The gain is calculated using variable x=(T60*32767/7000)*32768;
+
+ first values is used to get polynomial set for given room size,
+ For room sizes which are not in the table, linear interpolation can be used.
+
+ */
+
+/* Normalizing output including Reverb Level part (only shift up)*/
+const LVM_INT32 LVREV_GainPolyTable[24][5]={{1,17547434,128867434,-120988896,50761228,},
+ {2,18256869,172666902,-193169292,88345744,},
+ {3,16591311,139250151,-149667234,66770059,},
+ {4,17379977,170835131,-173579321,76278163,},
+ {5,18963512,210364934,-228623519,103435022,},
+ {6,17796318,135756417,-144084053,64327698,},
+ {7,17454695,174593214,-187513064,85146582,},
+ {8,17229257,140715570,-145790588,65361740,},
+ {9,17000547,163195946,-176733969,79562130,},
+ {10,16711699,142476304,-133339887,58366547,},
+ {13,18108419,149223697,-161762020,74397589,},
+ {15,16682043,124844884,-134284487,60082180,},
+ {17,16627346,120936430,-121766674,53146421,},
+ {20,17338325,125432694,-126616983,56534237,},
+ {25,16489146,99218217,-94597467,40616506,},
+ {30,15582373,84479043,-75365006,30952348,},
+ {40,16000669,84896611,-75031127,30696306,},
+ {50,15087054,71695031,-59349268,23279669,},
+ {60,15830714,68672971,-58211201,23671158,},
+ {70,15536061,66657972,-55901437,22560153,},
+ {75,15013145,48179917,-24138354,5232074,},
+ {80,15688738,50195036,-34206760,11515792,},
+ {90,16003322,48323661,-35607378,13153872,},
+ {100,15955223,48558201,-33706865,11715792,},
+ };
+
+/* End of file */
+
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
new file mode 100755
index 0000000..98471be
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $ */
+/* $Revision: 773 $ */
+/* $Date: 2010-06-14 10:43:54 +0200 (Mon, 14 Jun 2010) $ */
+/* */
+/****************************************************************************************/
+
+
+#ifndef _LVREV_TABLES_H_
+#define _LVREV_TABLES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+
+/****************************************************************************************/
+/* */
+/* Definitions */
+/* */
+/****************************************************************************************/
+
+extern const LVM_UINT16 LVM_FsTable[];
+extern LVM_UINT16 LVM_GetFsFromTable(LVM_Fs_en FsIndex);
+extern LVM_INT32 LVREV_GainPolyTable[24][5];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** _LVREV_TABLES_H_ **/
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
index fea44bf..668b151 100755
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
@@ -17,9 +17,9 @@
/************************************************************************************
- $Author: beq06068 $
- $Revision: 1307 $
- $Date: 2010-07-22 17:41:25 +0200 (Thu, 22 Jul 2010) $
+ $Author: nxp007753 $
+ $Revision: 1331 $
+ $Date: 2010-07-27 12:26:23 +0200 (Tue, 27 Jul 2010) $
*************************************************************************************/
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c
index 7ab6571..d8023d64 100755
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c
@@ -18,8 +18,8 @@
/************************************************************************************
$Author: nxp007753 $
- $Revision: 1315 $
- $Date: 2010-07-23 11:52:08 +0200 (Fri, 23 Jul 2010) $
+ $Revision: 1331 $
+ $Date: 2010-07-27 12:26:23 +0200 (Tue, 27 Jul 2010) $
*************************************************************************************/
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
index f5f7cd0..82a8db2 100755
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
@@ -17,9 +17,9 @@
/************************************************************************************
- $Author: beq06068 $
- $Revision: 1307 $
- $Date: 2010-07-22 17:41:25 +0200 (Thu, 22 Jul 2010) $
+ $Author: nxp007753 $
+ $Revision: 1331 $
+ $Date: 2010-07-27 12:26:23 +0200 (Tue, 27 Jul 2010) $
*************************************************************************************/
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c
index b67d824..83748e6 100755
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c
@@ -18,8 +18,8 @@
/************************************************************************************
$Author: nxp007753 $
- $Revision: 1315 $
- $Date: 2010-07-23 11:52:08 +0200 (Fri, 23 Jul 2010) $
+ $Revision: 1331 $
+ $Date: 2010-07-27 12:26:23 +0200 (Tue, 27 Jul 2010) $
*************************************************************************************/
diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk
index 7855dcd..2e9b9b4 100644
--- a/media/libeffects/lvm/wrapper/Android.mk
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -34,3 +34,36 @@
include $(BUILD_SHARED_LIBRARY)
+
+# reverb wrapper
+include $(CLEAR_VARS)
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_SRC_FILES:= \
+ Reverb/EffectReverb.cpp
+
+LOCAL_MODULE:= libreverbwrapper
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_STATIC_LIBRARIES += libreverb
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_LDLIBS += -ldl
+else
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/Reverb \
+ $(LOCAL_PATH)/../lib/Common/lib/ \
+ $(LOCAL_PATH)/../lib/Reverb/lib/ \
+
+
+include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index bcd646a..798271e 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -66,7 +66,9 @@
// Flag to allow a one time init of global memory, only happens on first call ever
int LvmInitFlag = LVM_FALSE;
-SessionContext GlobalSessionMemory[32];
+int LvmSessionsActive = 0;
+SessionContext GlobalSessionMemory[LVM_MAX_SESSIONS];
+int SessionIndex[LVM_MAX_SESSIONS];
// NXP SW BassBoost UUID
const effect_descriptor_t gBassBoostDescriptor = {
@@ -125,24 +127,24 @@
int LvmEffect_disable (EffectContext *pContext);
void LvmEffect_free (EffectContext *pContext);
int Effect_configure (EffectContext *pContext, effect_config_t *pConfig);
-int BassBoost_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue);
+int BassBoost_setParameter (EffectContext *pContext, void *pParam, void *pValue);
int BassBoost_getParameter (EffectContext *pContext,
- int32_t *pParam,
+ void *pParam,
size_t *pValueSize,
void *pValue);
-int Virtualizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue);
+int Virtualizer_setParameter (EffectContext *pContext, void *pParam, void *pValue);
int Virtualizer_getParameter (EffectContext *pContext,
- int32_t *pParam,
+ void *pParam,
size_t *pValueSize,
void *pValue);
-int Equalizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue);
+int Equalizer_setParameter (EffectContext *pContext, void *pParam, void *pValue);
int Equalizer_getParameter (EffectContext *pContext,
- int32_t *pParam,
+ void *pParam,
size_t *pValueSize,
void *pValue);
-int Volume_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue);
+int Volume_setParameter (EffectContext *pContext, void *pParam, void *pValue);
int Volume_getParameter (EffectContext *pContext,
- int32_t *pParam,
+ void *pParam,
size_t *pValueSize,
void *pValue);
@@ -189,6 +191,7 @@
int32_t ioId,
effect_interface_t *pInterface){
int ret;
+ int sessionNo;
int i;
EffectContext *pContext = new EffectContext;
@@ -199,7 +202,7 @@
return -EINVAL;
}
- if((sessionId < 0)||(sessionId >= LVM_MAX_SESSIONS)){
+ if(sessionId < 0){
LOGV("\tLVM_ERROR : EffectCreate sessionId is less than 0");
return -EINVAL;
}
@@ -210,16 +213,41 @@
LvmGlobalBundle_init();
}
+ LOGV("\tEffectCreate: There are %d LVM sessions acive\n", LvmSessionsActive);
+
+ // Find next available sessionNo
+ for(i=0; i<LVM_MAX_SESSIONS; i++){
+ if((SessionIndex[i] == -1)||(SessionIndex[i] == sessionId)){
+ sessionNo = i;
+ SessionIndex[i] = sessionId;
+ LOGV("\tEffectCreate: Allocating SessionNo %d for SessionId %d\n", sessionNo,sessionId);
+ break;
+ }
+ }
+
+ if(i==LVM_MAX_SESSIONS){
+ LOGV("\tLVM_ERROR : Cannot find memory to allocate for current session");
+ return -EINVAL;
+ }
// If this is the first create in this session
- if(GlobalSessionMemory[sessionId].bBundledEffectsEnabled == LVM_FALSE){
- LOGV("\tEffectCreate - This is the first effect in current session %d", sessionId);
- LOGV("\tEffectCreate - Setting up Bundled Effects Instance for session %d", sessionId);
+ if(GlobalSessionMemory[sessionNo].bBundledEffectsEnabled == LVM_FALSE){
+ LOGV("\tEffectCreate - This is the first effect in current sessionId %d sessionNo %d",
+ sessionId, sessionNo);
- GlobalSessionMemory[sessionId].bBundledEffectsEnabled = LVM_TRUE;
- GlobalSessionMemory[sessionId].pBundledContext = new BundledEffectContext;
+ LvmSessionsActive++;
- pContext->pBundledContext = GlobalSessionMemory[sessionId].pBundledContext;
- pContext->pBundledContext->SessionNo = sessionId;
+ if(LvmSessionsActive >= LVM_MAX_SESSIONS){
+ LOGV("\tLVM_ERROR : Number of active session is greater than LVM_MAX_SESSIONS (%d)",
+ LVM_MAX_SESSIONS);
+ return -EINVAL;
+ }
+
+ GlobalSessionMemory[sessionNo].bBundledEffectsEnabled = LVM_TRUE;
+ GlobalSessionMemory[sessionNo].pBundledContext = new BundledEffectContext;
+
+ pContext->pBundledContext = GlobalSessionMemory[sessionNo].pBundledContext;
+ pContext->pBundledContext->SessionNo = sessionNo;
+ pContext->pBundledContext->SessionId = sessionId;
pContext->pBundledContext->hInstance = NULL;
pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
@@ -267,37 +295,39 @@
}
}
else{
- pContext->pBundledContext = GlobalSessionMemory[sessionId].pBundledContext;
+ LOGV("\tEffectCreate - Assigning memory for previously created effect on sessionNo %d",
+ sessionNo);
+ pContext->pBundledContext =
+ GlobalSessionMemory[sessionNo].pBundledContext;
}
-
LOGV("\tEffectCreate - pBundledContext is %p", pContext->pBundledContext);
// Create each Effect
if (memcmp(uuid, &gBassBoostDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
// Create Bass Boost
LOGV("\tEffectCreate - Effect to be created is LVM_BASS_BOOST");
- GlobalSessionMemory[sessionId].bBassInstantiated = LVM_TRUE;
+ GlobalSessionMemory[pContext->pBundledContext->SessionNo].bBassInstantiated = LVM_TRUE;
pContext->itfe = &gLvmEffectInterface;
pContext->EffectType = LVM_BASS_BOOST;
} else if (memcmp(uuid, &gVirtualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
// Create Virtualizer
LOGV("\tEffectCreate - Effect to be created is LVM_VIRTUALIZER");
- GlobalSessionMemory[sessionId].bVirtualizerInstantiated = LVM_TRUE;
+ GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVirtualizerInstantiated=LVM_TRUE;
pContext->itfe = &gLvmEffectInterface;
pContext->EffectType = LVM_VIRTUALIZER;
} else if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
// Create Equalizer
LOGV("\tEffectCreate - Effect to be created is LVM_EQUALIZER");
- GlobalSessionMemory[sessionId].bEqualizerInstantiated = LVM_TRUE;
+ GlobalSessionMemory[pContext->pBundledContext->SessionNo].bEqualizerInstantiated = LVM_TRUE;
pContext->itfe = &gLvmEffectInterface;
pContext->EffectType = LVM_EQUALIZER;
} else if (memcmp(uuid, &gVolumeDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
// Create Volume
LOGV("\tEffectCreate - Effect to be created is LVM_VOLUME");
- GlobalSessionMemory[sessionId].bVolumeInstantiated = LVM_TRUE;
+ GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVolumeInstantiated = LVM_TRUE;
pContext->itfe = &gLvmEffectInterface;
pContext->EffectType = LVM_VOLUME;
@@ -316,6 +346,7 @@
LOGV("\n\tEffectRelease start %p", interface);
EffectContext * pContext = (EffectContext *)interface;
+ LOGV("\n\tEffectRelease start interface: %p, context %p", interface, pContext->pBundledContext);
if (pContext == NULL){
LOGV("\tLVM_ERROR : EffectRelease called with NULL pointer");
return -EINVAL;
@@ -349,13 +380,28 @@
fclose(pContext->pBundledContext->PcmInPtr);
fclose(pContext->pBundledContext->PcmOutPtr);
#endif
+
+ LvmSessionsActive--;
+ LOGV("\tEffectRelease: There are %d LVM sessions remaining\n", LvmSessionsActive);
+
+ // Clear the SessionIndex
+ for(int i=0; i<LVM_MAX_SESSIONS; i++){
+ if(SessionIndex[i] == pContext->pBundledContext->SessionId){
+ SessionIndex[i] = -1;
+ LOGV("\tEffectRelease: Clearing SessionIndex SessionNo %d for SessionId %d\n",
+ i, pContext->pBundledContext->SessionId);
+ break;
+ }
+ }
+
LOGV("\tEffectRelease: All effects are no longer instantiated\n");
GlobalSessionMemory[pContext->pBundledContext->SessionNo].bBundledEffectsEnabled =LVM_FALSE;
GlobalSessionMemory[pContext->pBundledContext->SessionNo].pBundledContext = LVM_NULL;
LOGV("\tEffectRelease: Freeing LVM Bundle memory\n");
LvmEffect_free(pContext);
- LOGV("\tEffectRelease: Deleting LVM Bundle context\n");
+ LOGV("\tEffectRelease: Deleting LVM Bundle context %p\n", pContext->pBundledContext);
delete pContext->pBundledContext;
+ pContext->pBundledContext = LVM_NULL;
}
// free the effect context for current effect
delete pContext;
@@ -374,6 +420,8 @@
GlobalSessionMemory[i].bBassInstantiated = LVM_FALSE;
GlobalSessionMemory[i].bVirtualizerInstantiated = LVM_FALSE;
GlobalSessionMemory[i].pBundledContext = LVM_NULL;
+
+ SessionIndex[i] = -1;
}
return;
}
@@ -505,6 +553,9 @@
params.SpeakerType = LVM_HEADPHONES;
pContext->pBundledContext->SampleRate = LVM_FS_44100;
+ pContext->pBundledContext->SamplesToExitCountEq = 44100*2*2; // 2 secs Stereo
+ pContext->pBundledContext->SamplesToExitCountBb = 44100*2*2; // 2 secs Stereo
+ pContext->pBundledContext->SamplesToExitCountVirt = 44100*2*2; // 2 secs Stereo
/* Concert Sound parameters */
params.VirtualizerOperatingMode = LVM_MODE_OFF;
@@ -842,21 +893,27 @@
switch (pConfig->inputCfg.samplingRate) {
case 8000:
SampleRate = LVM_FS_8000;
+ pContext->pBundledContext->SamplesPerSecond = 8000*2; // 2 secs Stereo
break;
case 16000:
SampleRate = LVM_FS_16000;
+ pContext->pBundledContext->SamplesPerSecond = 16000*2; // 2 secs Stereo
break;
case 22050:
SampleRate = LVM_FS_22050;
+ pContext->pBundledContext->SamplesPerSecond = 22050*2; // 2 secs Stereo
break;
case 32000:
SampleRate = LVM_FS_32000;
+ pContext->pBundledContext->SamplesPerSecond = 32000*2; // 2 secs Stereo
break;
case 44100:
SampleRate = LVM_FS_44100;
+ pContext->pBundledContext->SamplesPerSecond = 44100*2; // 2 secs Stereo
break;
case 48000:
SampleRate = LVM_FS_48000;
+ pContext->pBundledContext->SamplesPerSecond = 48000*2; // 2 secs Stereo
break;
default:
LOGV("\tEffect_Configure invalid sampling rate %d", pConfig->inputCfg.samplingRate);
@@ -881,6 +938,7 @@
LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "Effect_configure")
LOGV("\tEffect_configure Succesfully called LVM_SetControlParameters\n");
+ pContext->pBundledContext->SampleRate = SampleRate;
}else{
//LOGV("\tEffect_configure keep sampling rate at %d", SampleRate);
@@ -1461,7 +1519,7 @@
LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
LVM_INT16 Balance = 0;
-
+
pContext->pBundledContext->positionSaved = position;
Balance = VolumeConvertStereoPosition(pContext->pBundledContext->positionSaved);
@@ -1614,11 +1672,12 @@
//----------------------------------------------------------------------------
int BassBoost_getParameter(EffectContext *pContext,
- int32_t *pParam,
+ void *pParam,
size_t *pValueSize,
void *pValue){
int status = 0;
- int32_t param = *pParam++;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
int32_t param2;
char *name;
@@ -1685,13 +1744,14 @@
//
//----------------------------------------------------------------------------
-int BassBoost_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue){
+int BassBoost_setParameter (EffectContext *pContext, void *pParam, void *pValue){
int status = 0;
int16_t strength;
+ int32_t *pParamTemp = (int32_t *)pParam;
//LOGV("\tBassBoost_setParameter start");
- switch (*pParam){
+ switch (*pParamTemp){
case BASSBOOST_PARAM_STRENGTH:
strength = *(int16_t *)pValue;
//LOGV("\tBassBoost_setParameter() BASSBOOST_PARAM_STRENGTH value is %d", strength);
@@ -1700,7 +1760,7 @@
//LOGV("\tBassBoost_setParameter() Called pBassBoost->BassSetStrength");
break;
default:
- LOGV("\tLVM_ERROR : BassBoost_setParameter() invalid param %d", *pParam);
+ LOGV("\tLVM_ERROR : BassBoost_setParameter() invalid param %d", *pParamTemp);
break;
}
@@ -1730,11 +1790,12 @@
//----------------------------------------------------------------------------
int Virtualizer_getParameter(EffectContext *pContext,
- int32_t *pParam,
+ void *pParam,
size_t *pValueSize,
void *pValue){
int status = 0;
- int32_t param = *pParam++;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
int32_t param2;
char *name;
@@ -1802,13 +1863,15 @@
//
//----------------------------------------------------------------------------
-int Virtualizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue){
+int Virtualizer_setParameter (EffectContext *pContext, void *pParam, void *pValue){
int status = 0;
int16_t strength;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
//LOGV("\tVirtualizer_setParameter start");
- switch (*pParam){
+ switch (param){
case VIRTUALIZER_PARAM_STRENGTH:
strength = *(int16_t *)pValue;
//LOGV("\tVirtualizer_setParameter() VIRTUALIZER_PARAM_STRENGTH value is %d", strength);
@@ -1817,7 +1880,7 @@
//LOGV("\tVirtualizer_setParameter() Called pVirtualizer->setStrength");
break;
default:
- LOGV("\tLVM_ERROR : Virtualizer_setParameter() invalid param %d", *pParam);
+ LOGV("\tLVM_ERROR : Virtualizer_setParameter() invalid param %d", param);
break;
}
@@ -1846,12 +1909,13 @@
//
//----------------------------------------------------------------------------
int Equalizer_getParameter(EffectContext *pContext,
- int32_t *pParam,
+ void *pParam,
size_t *pValueSize,
void *pValue){
int status = 0;
int bMute = 0;
- int32_t param = *pParam++;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
int32_t param2;
char *name;
@@ -1924,7 +1988,7 @@
break;
case EQ_PARAM_BAND_LEVEL:
- param2 = *pParam;
+ param2 = *pParamTemp;
if (param2 >= FIVEBAND_NUMBANDS) {
status = -EINVAL;
break;
@@ -1935,7 +1999,7 @@
break;
case EQ_PARAM_CENTER_FREQ:
- param2 = *pParam;
+ param2 = *pParamTemp;
if (param2 >= FIVEBAND_NUMBANDS) {
status = -EINVAL;
break;
@@ -1946,7 +2010,7 @@
break;
case EQ_PARAM_BAND_FREQ_RANGE:
- param2 = *pParam;
+ param2 = *pParamTemp;
if (param2 >= FIVEBAND_NUMBANDS) {
status = -EINVAL;
break;
@@ -1957,7 +2021,7 @@
break;
case EQ_PARAM_GET_BAND:
- param2 = *pParam;
+ param2 = *pParamTemp;
*(uint16_t *)pValue = (uint16_t)EqualizerGetBand(pContext, param2);
//LOGV("\tEqualizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d",
// param2, *(int32_t *)pValue);
@@ -1974,7 +2038,7 @@
break;
case EQ_PARAM_GET_PRESET_NAME:
- param2 = *pParam;
+ param2 = *pParamTemp;
if (param2 >= EqualizerGetNumPresets()) {
//if (param2 >= 20) { // AGO FIX
status = -EINVAL;
@@ -2022,12 +2086,14 @@
// Outputs:
//
//----------------------------------------------------------------------------
-int Equalizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue){
+int Equalizer_setParameter (EffectContext *pContext, void *pParam, void *pValue){
int status = 0;
int32_t preset;
int32_t band;
int32_t level;
- int32_t param = *pParam++;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
+
//LOGV("\tEqualizer_setParameter start");
switch (param) {
@@ -2042,7 +2108,7 @@
EqualizerSetPreset(pContext, preset);
break;
case EQ_PARAM_BAND_LEVEL:
- band = *pParam;
+ band = *pParamTemp;
level = (int32_t)(*(int16_t *)pValue);
//LOGV("\tEqualizer_setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
if (band >= FIVEBAND_NUMBANDS) {
@@ -2102,13 +2168,13 @@
//----------------------------------------------------------------------------
int Volume_getParameter(EffectContext *pContext,
- int32_t *pParam,
+ void *pParam,
size_t *pValueSize,
void *pValue){
int status = 0;
int bMute = 0;
- int32_t param = *pParam++;
- int32_t param2;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;;
char *name;
LOGV("\tVolume_getParameter start");
@@ -2195,16 +2261,18 @@
//
//----------------------------------------------------------------------------
-int Volume_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue){
+int Volume_setParameter (EffectContext *pContext, void *pParam, void *pValue){
int status = 0;
int16_t level;
int16_t position;
uint32_t mute;
uint32_t positionEnabled;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
LOGV("\tVolume_setParameter start");
- switch (*pParam){
+ switch (param){
case VOLUME_PARAM_LEVEL:
level = *(int16_t *)pValue;
LOGV("\tVolume_setParameter() VOLUME_PARAM_LEVEL value is %d", level);
@@ -2237,7 +2305,7 @@
break;
default:
- LOGV("\tLVM_ERROR : Volume_setParameter() invalid param %d", *pParam);
+ LOGV("\tLVM_ERROR : Volume_setParameter() invalid param %d", param);
break;
}
@@ -2299,13 +2367,27 @@
audio_buffer_t *inBuffer,
audio_buffer_t *outBuffer){
EffectContext * pContext = (EffectContext *) self;
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
int status = 0;
+ int status2Sec = 0;
int lvmStatus = 0;
LVM_INT16 *in = (LVM_INT16 *)inBuffer->raw;
LVM_INT16 *out = (LVM_INT16 *)outBuffer->raw;
//LOGV("\tEffect_process Start : Enabled = %d Called = %d",
//pContext->pBundledContext->NumberEffectsEnabled,pContext->pBundledContext->NumberEffectsCalled);
+// LOGV("\tEffect_process Start : Samples left %d %d %d",
+// pContext->pBundledContext->SamplesToExitCountBb,
+// pContext->pBundledContext->SamplesToExitCountVirt,
+// pContext->pBundledContext->SamplesToExitCountEq);
+
+// LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+// LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeGetStereoPosition")
+// if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+// LOGV("\tEffect_process Internal Operating Modes: BB %d VIRT %d EQ %d",
+// ActiveParams.BE_OperatingMode, ActiveParams.VirtualizerOperatingMode,
+// ActiveParams.EQNB_OperatingMode);
if (pContext == NULL){
LOGV("\tLVM_ERROR : Effect_process() ERROR pContext == NULL");
@@ -2319,23 +2401,44 @@
}
if ((pContext->pBundledContext->bBassEnabled == LVM_FALSE)&&
(pContext->EffectType == LVM_BASS_BOOST)){
- LOGV("\tEffect_process() ERROR LVM_BASS_BOOST Effect is not enabled");
+ //LOGV("\tEffect_process() LVM_BASS_BOOST Effect is not enabled");
+ if(pContext->pBundledContext->SamplesToExitCountBb > 0){
+ status2Sec = -ENODATA;
+ pContext->pBundledContext->SamplesToExitCountBb -= outBuffer->frameCount * 2; // STEREO
+ //LOGV("\tEffect_process: Waiting for 2 secs to turn off BASS_BOOST, %d samples left",
+ // pContext->pBundledContext->SamplesToExitCountBb);
+ } else {
status = -ENODATA;
+ }
}
if ((pContext->pBundledContext->bVolumeEnabled == LVM_FALSE)&&
(pContext->EffectType == LVM_VOLUME)){
- LOGV("\tEffect_process() ERROR LVM_VOLUME Effect is not enabled");
+ //LOGV("\tEffect_process() LVM_VOLUME Effect is not enabled");
status = -ENODATA;
}
if ((pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE)&&
(pContext->EffectType == LVM_EQUALIZER)){
- LOGV("\tEffect_process() ERROR LVM_EQUALIZER Effect is not enabled");
- status = -ENODATA;
+ //LOGV("\tEffect_process() LVM_EQUALIZER Effect is not enabled");
+ if(pContext->pBundledContext->SamplesToExitCountEq > 0){
+ status2Sec = -ENODATA;
+ pContext->pBundledContext->SamplesToExitCountEq -= outBuffer->frameCount * 2; // STEREO
+ //LOGV("\tEffect_process: Waiting for 2 secs to turn off EQUALIZER, %d samples left",
+ // pContext->pBundledContext->SamplesToExitCountEq);
+ } else {
+ status = -ENODATA;
+ }
}
if ((pContext->pBundledContext->bVirtualizerEnabled == LVM_FALSE)&&
(pContext->EffectType == LVM_VIRTUALIZER)){
- LOGV("\tEffect_process() ERROR LVM_VIRTUALIZER Effect is not enabled");
- status = -ENODATA;
+ //LOGV("\tEffect_process() LVM_VIRTUALIZER Effect is not enabled");
+ if(pContext->pBundledContext->SamplesToExitCountVirt > 0){
+ status2Sec = -ENODATA;
+ pContext->pBundledContext->SamplesToExitCountVirt -= outBuffer->frameCount * 2;// STEREO
+ //LOGV("\tEffect_process: Waiting for 2 secs to turn off VIRTUALIZER, %d samples left",
+ // pContext->pBundledContext->SamplesToExitCountVirt);
+ } else {
+ status = -ENODATA;
+ }
}
// If this is the last frame of an effect process its output with no effect
@@ -2352,7 +2455,7 @@
}
}
- if(status != -ENODATA){
+ if((status2Sec != -ENODATA)&&(status != -ENODATA)){
pContext->pBundledContext->NumberEffectsCalled++;
}
@@ -2496,7 +2599,7 @@
int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
p->status = android::BassBoost_getParameter(pContext,
- (int32_t *)p->data,
+ p->data,
(size_t *)&p->vsize,
p->data + voffset);
@@ -2527,7 +2630,7 @@
int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
p->status = android::Virtualizer_getParameter(pContext,
- (int32_t *)p->data,
+ (void *)p->data,
(size_t *)&p->vsize,
p->data + voffset);
@@ -2558,8 +2661,10 @@
int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
- p->status = android::Equalizer_getParameter(pContext, (int32_t *)p->data, &p->vsize,
- p->data + voffset);
+ p->status = android::Equalizer_getParameter(pContext,
+ p->data,
+ &p->vsize,
+ p->data + voffset);
*replySize = sizeof(effect_param_t) + voffset + p->vsize;
@@ -2590,7 +2695,7 @@
int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
p->status = android::Volume_getParameter(pContext,
- (int32_t *)p->data,
+ (void *)p->data,
(size_t *)&p->vsize,
p->data + voffset);
@@ -2636,7 +2741,7 @@
// cmdSize, sizeof(effect_param_t), p->psize, p->vsize );
*(int *)pReplyData = android::BassBoost_setParameter(pContext,
- (int32_t *)p->data,
+ (void *)p->data,
p->data + p->psize);
}
if(pContext->EffectType == LVM_VIRTUALIZER){
@@ -2669,7 +2774,7 @@
// cmdSize, sizeof(effect_param_t), p->psize, p->vsize );
*(int *)pReplyData = android::Virtualizer_setParameter(pContext,
- (int32_t *)p->data,
+ (void *)p->data,
p->data + p->psize);
}
if(pContext->EffectType == LVM_EQUALIZER){
@@ -2689,7 +2794,7 @@
effect_param_t *p = (effect_param_t *) pCmdData;
*(int *)pReplyData = android::Equalizer_setParameter(pContext,
- (int32_t *)p->data,
+ (void *)p->data,
p->data + p->psize);
}
if(pContext->EffectType == LVM_VOLUME){
@@ -2711,14 +2816,14 @@
effect_param_t *p = (effect_param_t *) pCmdData;
*(int *)pReplyData = android::Volume_setParameter(pContext,
- (int32_t *)p->data,
+ (void *)p->data,
p->data + p->psize);
}
//LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_PARAM end");
} break;
case EFFECT_CMD_ENABLE:
- //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE start");
+ LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE start");
if (pReplyData == NULL || *replySize != sizeof(int)){
LOGV("\tLVM_ERROR : Effect_command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
return -EINVAL;
@@ -2768,6 +2873,14 @@
*(int *)pReplyData = 0;
pContext->pBundledContext->NumberEffectsEnabled++;
android::LvmEffect_enable(pContext);
+ pContext->pBundledContext->SamplesToExitCountEq =
+ (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*1); // 0.1 secs Stereo
+ pContext->pBundledContext->SamplesToExitCountBb =
+ (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*6); // 2 secs Stereo
+ pContext->pBundledContext->SamplesToExitCountVirt =
+ (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*1); // 2 secs Stereo
+ LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE Samples to Exit = %d",
+ pContext->pBundledContext->SamplesToExitCountBb);
//LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE NumberEffectsEnabled = %d",
// pContext->pBundledContext->NumberEffectsEnabled);
//LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE end");
@@ -2906,11 +3019,8 @@
}
case EFFECT_CMD_SET_VOLUME:
{
- int32_t channels = cmdSize/sizeof(int32_t);
int32_t vol = *(int32_t *)pCmdData;
- int16_t vol_db;
int16_t dB;
- int16_t vol_db_rnd;
int32_t vol_ret[2] = {1<<24,1<<24}; // Apply no volume
// if pReplyData is NULL, VOL_CTRL is delegated to another effect
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index d009bf9..1bee974 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -58,6 +58,7 @@
struct BundledEffectContext{
LVM_Handle_t hInstance; /* Instance handle */
int SessionNo; /* Current session number */
+ int SessionId; /* Current session id */
bool bVolumeEnabled; /* Flag for Volume */
bool bEqualizerEnabled; /* Flag for EQ */
bool bBassEnabled; /* Flag for Bass */
@@ -80,6 +81,10 @@
bool bStereoPositionEnabled;
int frameCount;
LVM_Fs_en SampleRate;
+ int SamplesPerSecond;
+ int SamplesToExitCountEq;
+ int SamplesToExitCountBb;
+ int SamplesToExitCountVirt;
#ifdef LVM_PCM
FILE *PcmInPtr;
FILE *PcmOutPtr;
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
new file mode 100755
index 0000000..2043e44
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -0,0 +1,1820 @@
+/*
+ * Copyright (C) 2010-2010 NXP Software
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Reverb"
+#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
+#define LOG_NDEBUG 0
+
+#include <cutils/log.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <new>
+#include <EffectReverb.h>
+#include <LVREV.h>
+
+#define MAX_NUM_BANDS 5
+#define MAX_CALL_SIZE 256
+#define LVREV_MAX_T60 7000
+#define LVREV_MAX_REVERB_LEVEL 2000
+
+//#define LVM_PCM
+
+// effect_interface_t interface implementation for reverb
+extern "C" const struct effect_interface_s gReverbInterface;
+
+#define LVM_ERROR_CHECK(LvmStatus, callingFunc, calledFunc){\
+ if (LvmStatus == LVREV_NULLADDRESS){\
+ LOGV("\tLVREV_ERROR : Parameter error - "\
+ "null pointer returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+ }\
+ if (LvmStatus == LVREV_INVALIDNUMSAMPLES){\
+ LOGV("\tLVREV_ERROR : Parameter error - "\
+ "bad number of samples returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+ }\
+ if (LvmStatus == LVREV_OUTOFRANGE){\
+ LOGV("\tLVREV_ERROR : Parameter error - "\
+ "out of range returned by %s in %s\n", callingFunc, calledFunc);\
+ }\
+ }
+
+// Namespaces
+namespace android {
+namespace {
+
+/************************************************************************************/
+/* */
+/* 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
+
+// NXP SW Reverb UUID
+const effect_descriptor_t gReverbDescriptor = {
+ { 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),
+ 0, // TODO
+ 1,
+ "Reverb",
+ "NXP Software Ltd.",
+};
+
+struct ReverbContext{
+ const struct effect_interface_s *itfe;
+ effect_config_t config;
+ LVREV_Handle_t hInstance;
+ int16_t SavedRoomLevel;
+ int16_t SavedHfLevel;
+ int16_t SavedDecayTime;
+ int16_t SavedDecayHfRatio;
+ int16_t SavedReverbLevel;
+ int16_t SavedDiffusion;
+ int16_t SavedDensity;
+ bool bEnabled;
+ #ifdef LVM_PCM
+ FILE *PcmInPtr;
+ FILE *PcmOutPtr;
+ #endif
+ LVM_Fs_en SampleRate;
+};
+
+//--- local function prototypes
+int Reverb_init (ReverbContext *pContext);
+void Reverb_free (ReverbContext *pContext);
+int Reverb_configure (ReverbContext *pContext, effect_config_t *pConfig);
+int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue);
+int Reverb_getParameter (ReverbContext *pContext,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue);
+
+/* Effect Library Interface Implementation */
+extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects){
+ LOGV("\n\tEffectQueryNumberEffects start");
+ *pNumEffects = 1;
+ LOGV("\tEffectQueryNumberEffects creating %d effects", *pNumEffects);
+ LOGV("\tEffectQueryNumberEffects end\n");
+ return 0;
+} /* end EffectQueryNumberEffects */
+
+extern "C" int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor){
+ LOGV("\n\tEffectQueryEffect start");
+ LOGV("\tEffectQueryEffect processing index %d", index);
+ if (pDescriptor == NULL){
+ LOGV("\tLVM_ERROR : EffectQueryEffect was passed NULL pointer");
+ return -EINVAL;
+ }
+ if (index > 0){
+ LOGV("\tLVM_ERROR : EffectQueryEffect index out of range %d", index);
+ return -ENOENT;
+ }
+ memcpy(pDescriptor, &gReverbDescriptor, sizeof(effect_descriptor_t));
+ LOGV("\tEffectQueryEffect end\n");
+ return 0;
+} /* end EffectQueryEffect */
+
+extern "C" int EffectCreate(effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_interface_t *pInterface){
+ int ret;
+ int i;
+
+ LOGV("\t\nEffectCreate start");
+
+ if (pInterface == NULL || uuid == NULL){
+ LOGV("\tLVM_ERROR : EffectCreate() called with NULL pointer");
+ return -EINVAL;
+ }
+
+ if (memcmp(uuid, &gReverbDescriptor.uuid, sizeof(effect_uuid_t)) != 0){
+ LOGV("\tLVM_ERROR : EffectCreate() invalid UUID");
+ return -EINVAL;
+ }
+
+ ReverbContext *pContext = new ReverbContext;
+
+ pContext->itfe = &gReverbInterface;
+ pContext->hInstance = NULL;
+
+ LOGV("\tEffectCreate - Calling Reverb_init");
+ ret = Reverb_init(pContext);
+
+ if (ret < 0){
+ LOGV("\tLVM_ERROR : EffectCreate() init failed");
+ delete pContext;
+ return ret;
+ }
+
+ *pInterface = (effect_interface_t)pContext;
+
+ #ifdef LVM_PCM
+ pContext->PcmInPtr = NULL;
+ pContext->PcmOutPtr = NULL;
+
+ pContext->PcmInPtr = fopen("/data/tmp/reverb_pcm_in.pcm", "w");
+ pContext->PcmOutPtr = fopen("/data/tmp/reverb_pcm_out.pcm", "w");
+
+ if((pContext->PcmInPtr == NULL)||
+ (pContext->PcmOutPtr == NULL)){
+ return -EINVAL;
+ }
+ #endif
+
+ LOGV("\tEffectCreate %p, size %d", pContext, sizeof(ReverbContext));
+ LOGV("\tEffectCreate end\n");
+ return 0;
+} /* end EffectCreate */
+
+extern "C" int EffectRelease(effect_interface_t interface){
+ ReverbContext * pContext = (ReverbContext *)interface;
+
+ LOGV("\tEffectRelease %p", interface);
+ if (pContext == NULL){
+ LOGV("\tLVM_ERROR : EffectRelease called with NULL pointer");
+ return -EINVAL;
+ }
+
+ #ifdef LVM_PCM
+ fclose(pContext->PcmInPtr);
+ fclose(pContext->PcmOutPtr);
+ #endif
+ Reverb_free(pContext);
+ delete pContext;
+ return 0;
+} /* end EffectRelease */
+
+/* local functions */
+#define CHECK_ARG(cond) { \
+ if (!(cond)) { \
+ LOGV("\tLVM_ERROR : Invalid argument: "#cond); \
+ return -EINVAL; \
+ } \
+}
+
+//----------------------------------------------------------------------------
+// MonoTo2I_32()
+//----------------------------------------------------------------------------
+// Purpose:
+// Convert MONO to STEREO
+//
+//----------------------------------------------------------------------------
+
+void MonoTo2I_32( const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT16 ii;
+ src += (n-1);
+ dst += ((n*2)-1);
+
+ for (ii = n; ii != 0; ii--)
+ {
+ *dst = *src;
+ dst--;
+
+ *dst = *src;
+ dst--;
+ src--;
+ }
+
+ return;
+}
+
+//----------------------------------------------------------------------------
+// From2iToMono_32()
+//----------------------------------------------------------------------------
+// Purpose:
+// Convert STEREO to MONO
+//
+//----------------------------------------------------------------------------
+
+void From2iToMono_32( const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT16 ii;
+ LVM_INT32 Temp;
+
+ for (ii = n; ii != 0; ii--)
+ {
+ Temp = (*src>>1);
+ src++;
+
+ Temp +=(*src>>1);
+ src++;
+
+ *dst = Temp;
+ dst++;
+ }
+
+ return;
+}
+//----------------------------------------------------------------------------
+// process()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the Reverb
+//
+// Inputs:
+// pIn: pointer to stereo/mono 16 bit input data
+// pOut: pointer to stereo 16 bit output data
+// frameCount: Frames to process
+// pContext: effect engine context
+// strength strength to be applied
+//
+// Outputs:
+// pOut: pointer to updated stereo 16 bit output data
+//
+//----------------------------------------------------------------------------
+
+int process( LVM_INT16 *pIn,
+ LVM_INT16 *pOut,
+ int frameCount,
+ ReverbContext *pContext){
+
+ LVM_INT16 samplesPerFrame = 0;
+ LVREV_ReturnStatus_en LvmStatus = LVREV_SUCCESS; /* Function call status */
+
+ LVM_INT32 *InFrames32;
+ LVM_INT32 *OutFrames32;
+ LVM_INT16 *OutFrames16;
+
+
+ // Check that the input is either mono or stereo
+ if(pContext->config.inputCfg.channels == CHANNEL_STEREO){
+ samplesPerFrame = 2;
+ } else if (pContext->config.inputCfg.channels == CHANNEL_MONO){
+ samplesPerFrame = 1;
+ } else {
+ LOGV("\tLVREV_ERROR : process invalid PCM format");
+ return -EINVAL;
+ }
+
+ InFrames32 = (LVM_INT32 *)malloc(frameCount * sizeof(LVM_INT32) * 2);
+ OutFrames32 = (LVM_INT32 *)malloc(frameCount * sizeof(LVM_INT32) * 2);
+ OutFrames16 = (LVM_INT16 *)OutFrames32;
+
+ // Check for NULL pointers
+ if((InFrames32 == NULL)||(OutFrames32 == NULL)){
+ LOGV("\tLVREV_ERROR : process failed to allocate memory for temporary buffers ");
+ return -EINVAL;
+ }
+
+ #ifdef LVM_PCM
+ fwrite(pIn, frameCount*sizeof(LVM_INT16)*samplesPerFrame, 1, pContext->PcmInPtr);
+ fflush(pContext->PcmInPtr);
+ #endif
+
+ // Convert to Input 32 bits
+ for(int i=0; i<frameCount*samplesPerFrame; i++){
+ InFrames32[i] = (LVM_INT32)pIn[i]<<8;
+ }
+
+ // If the input was MONO, convert to STEREO
+ if(pContext->config.inputCfg.channels == CHANNEL_MONO){
+ //LOGV("\tConverting Output from MONO to STEREO");
+ MonoTo2I_32(InFrames32, InFrames32, frameCount);
+ }
+
+ //LOGV("\tProcess, frames: %d, InFormat: %d(MONO=%d), OutFormat: %d(STEREO=%d)",
+ //frameCount, pContext->config.inputCfg.channels, CHANNEL_MONO,
+ //pContext->config.outputCfg.channels, CHANNEL_STEREO);
+
+ /* Process the samples */
+ LvmStatus = LVREV_Process(pContext->hInstance, /* Instance handle */
+ InFrames32, /* Input buffer */
+ OutFrames32, /* Output buffer */
+ frameCount); /* Number of samples to read */
+
+ 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);
+ }
+
+ #ifdef LVM_PCM
+ fwrite(OutFrames16, frameCount*sizeof(LVM_INT16)*samplesPerFrame, 1, pContext->PcmOutPtr);
+ fflush(pContext->PcmOutPtr);
+ #endif
+
+ // Accumulate if required
+ 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];
+ }
+ }else{
+ //LOGV("\tBuffer access is WRITE");
+ memcpy(pOut, OutFrames16, frameCount*sizeof(LVM_INT16)*2); // 2 is for stereo output
+ }
+
+ free(InFrames32);
+ free(OutFrames32);
+
+ return 0;
+} /* end process */
+
+//----------------------------------------------------------------------------
+// Reverb_free()
+//----------------------------------------------------------------------------
+// Purpose: Free all memory associated with the Bundle.
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+void Reverb_free(ReverbContext *pContext){
+
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVREV_ControlParams_st params; /* Control Parameters */
+ LVREV_MemoryTable_st MemTab;
+
+ /* Free the algorithm memory */
+ LvmStatus = LVREV_GetMemoryTable(pContext->hInstance,
+ &MemTab,
+ LVM_NULL);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetMemoryTable", "Reverb_free")
+
+ for (int i=0; i<LVM_NR_MEMORY_REGIONS; i++){
+ if (MemTab.Region[i].Size != 0){
+ if (MemTab.Region[i].pBaseAddress != NULL){
+ LOGV("\tfree() - START freeing %ld bytes for region %u at %p\n",
+ MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+
+ free(MemTab.Region[i].pBaseAddress);
+
+ LOGV("\tfree() - END freeing %ld bytes for region %u at %p\n",
+ MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+ }else{
+ LOGV("\tLVM_ERROR : free() - trying to free with NULL pointer %ld bytes "
+ "for region %u at %p ERROR\n",
+ MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+ }
+ }
+ }
+} /* end Reverb_free */
+
+//----------------------------------------------------------------------------
+// Reverb_configure()
+//----------------------------------------------------------------------------
+// Purpose: Set input and output audio configuration.
+//
+// Inputs:
+// pContext: effect engine context
+// pConfig: pointer to effect_config_t structure holding input and output
+// configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Reverb_configure(ReverbContext *pContext, effect_config_t *pConfig){
+ LVM_Fs_en SampleRate;
+ //LOGV("\tReverb_configure start");
+
+ CHECK_ARG(pContext != NULL);
+ CHECK_ARG(pConfig != NULL);
+
+ CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
+ CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
+ CHECK_ARG(pConfig->outputCfg.channels == CHANNEL_STEREO);
+ CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
+ || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+ CHECK_ARG(pConfig->inputCfg.format == SAMPLE_FORMAT_PCM_S15);
+
+ if(pConfig->inputCfg.samplingRate != 44100){
+ return -EINVAL;
+ }
+
+ //LOGV("\tReverb_configure calling memcpy");
+ memcpy(&pContext->config, pConfig, sizeof(effect_config_t));
+
+ switch (pConfig->inputCfg.samplingRate) {
+ case 8000:
+ SampleRate = LVM_FS_8000;
+ break;
+ case 16000:
+ SampleRate = LVM_FS_16000;
+ break;
+ case 22050:
+ SampleRate = LVM_FS_22050;
+ break;
+ case 32000:
+ SampleRate = LVM_FS_32000;
+ break;
+ case 44100:
+ SampleRate = LVM_FS_44100;
+ break;
+ case 48000:
+ SampleRate = LVM_FS_48000;
+ break;
+ default:
+ LOGV("\rReverb_Configure invalid sampling rate %d", pConfig->inputCfg.samplingRate);
+ return -EINVAL;
+ }
+
+ if(pContext->SampleRate != SampleRate){
+
+ LVREV_ControlParams_st ActiveParams;
+ LVREV_ReturnStatus_en LvmStatus = LVREV_SUCCESS;
+
+ //LOGV("\tReverb_configure change sampling rate to %d", SampleRate);
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance,
+ &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "Reverb_configure")
+ if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
+
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "Reverb_configure")
+ //LOGV("\tReverb_configure Succesfully called LVREV_SetControlParameters\n");
+
+ }else{
+ //LOGV("\tReverb_configure keep sampling rate at %d", SampleRate);
+ }
+
+ //LOGV("\tReverb_configure End");
+ return 0;
+} /* end Reverb_configure */
+
+
+//----------------------------------------------------------------------------
+// Reverb_init()
+//----------------------------------------------------------------------------
+// Purpose: Initialize engine with default configuration
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+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;
+ }
+
+ CHECK_ARG(pContext != NULL);
+
+ if (pContext->hInstance != NULL){
+ Reverb_free(pContext);
+ }
+
+ pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ pContext->config.inputCfg.channels = channel_mode;
+ pContext->config.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ pContext->config.inputCfg.samplingRate = 44100;
+ pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
+ pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
+ pContext->config.inputCfg.bufferProvider.cookie = NULL;
+ pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
+ pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+ pContext->config.outputCfg.channels = CHANNEL_STEREO;
+ pContext->config.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ pContext->config.outputCfg.samplingRate = 44100;
+ pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
+ pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+ pContext->config.outputCfg.bufferProvider.cookie = NULL;
+ pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVREV_ControlParams_st params; /* Control Parameters */
+ LVREV_InstanceParams_st InstParams; /* Instance parameters */
+ LVREV_MemoryTable_st MemTab; /* Memory allocation table */
+ bool bMallocFailure = LVM_FALSE;
+
+ /* Set the capabilities */
+ InstParams.MaxBlockSize = MAX_CALL_SIZE;
+ InstParams.SourceFormat = LVM_STEREO;
+ InstParams.NumDelays = LVREV_DELAYLINES_4;
+
+ /* Allocate memory, forcing alignment */
+ LvmStatus = LVREV_GetMemoryTable(LVM_NULL,
+ &MemTab,
+ &InstParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetMemoryTable", "Reverb_init")
+ if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
+
+ LOGV("\tCreateInstance Succesfully called LVM_GetMemoryTable\n");
+
+ /* Allocate memory */
+ for (int i=0; i<LVM_NR_MEMORY_REGIONS; i++){
+ if (MemTab.Region[i].Size != 0){
+ MemTab.Region[i].pBaseAddress = malloc(MemTab.Region[i].Size);
+
+ if (MemTab.Region[i].pBaseAddress == LVM_NULL){
+ LOGV("\tLVREV_ERROR :Reverb_init CreateInstance Failed to allocate %ld bytes for region %u\n",
+ MemTab.Region[i].Size, i );
+ bMallocFailure = LVM_TRUE;
+ }else{
+ LOGV("\tReverb_init CreateInstance allocate %ld bytes for region %u at %p\n",
+ MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+ }
+ }
+ }
+
+ /* If one or more of the memory regions failed to allocate, free the regions that were
+ * succesfully allocated and return with an error
+ */
+ if(bMallocFailure == LVM_TRUE){
+ for (int i=0; i<LVM_NR_MEMORY_REGIONS; i++){
+ if (MemTab.Region[i].pBaseAddress == LVM_NULL){
+ LOGV("\tLVM_ERROR :Reverb_init CreateInstance Failed to allocate %ld bytes for region %u"
+ " - Not freeing\n", MemTab.Region[i].Size, i );
+ }else{
+ LOGV("\tLVM_ERROR :Reverb_init CreateInstance Failed: but allocated %ld bytes for region %u "
+ "at %p- free\n", MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+ free(MemTab.Region[i].pBaseAddress);
+ }
+ }
+ return -EINVAL;
+ }
+ LOGV("\tReverb_init CreateInstance Succesfully malloc'd memory\n");
+
+ /* Initialise */
+ pContext->hInstance = LVM_NULL;
+
+ /* Init sets the instance handle */
+ LvmStatus = LVREV_GetInstanceHandle(&pContext->hInstance,
+ &MemTab,
+ &InstParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetInstanceHandle", "Reverb_init")
+ if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
+
+ LOGV("\tReverb_init CreateInstance Succesfully called LVM_GetInstanceHandle\n");
+
+ /* Set the initial process parameters */
+ /* General parameters */
+ params.OperatingMode = LVM_MODE_ON;
+ params.SampleRate = LVM_FS_44100;
+ params.SourceFormat = LVM_STEREO;
+
+ /* 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];
+
+ /* 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
+ * quantisation like effect when returning
+ */
+ pContext->SavedRoomLevel = -6000;
+ pContext->SavedHfLevel = 0;
+ pContext->bEnabled = LVM_FALSE;
+ pContext->SavedDecayTime = params.T60;
+ pContext->SavedDecayHfRatio = params.Damping*10;
+ pContext->SavedDensity = params.RoomSize*10;
+ pContext->SavedDiffusion = params.Density*10;
+ pContext->SavedReverbLevel = -6000;
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance,
+ ¶ms);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "Reverb_init")
+ if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
+
+ LOGV("\tReverb_init CreateInstance Succesfully called LVREV_SetControlParameters\n");
+ LOGV("\tReverb_init End");
+ return 0;
+} /* end Reverb_init */
+
+//----------------------------------------------------------------------------
+// ReverbConvertLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Convert level from OpenSL ES format to LVM format
+//
+// Inputs:
+// level level to be applied
+//
+//----------------------------------------------------------------------------
+
+int16_t ReverbConvertLevel(int16_t level){
+ static int16_t LevelArray[101] =
+ {
+ -12000, -4000, -3398, -3046, -2796, -2603, -2444, -2310, -2194, -2092,
+ -2000, -1918, -1842, -1773, -1708, -1648, -1592, -1540, -1490, -1443,
+ -1398, -1356, -1316, -1277, -1240, -1205, -1171, -1138, -1106, -1076,
+ -1046, -1018, -990, -963, -938, -912, -888, -864, -841, -818,
+ -796, -775, -754, -734, -714, -694, -675, -656, -638, -620,
+ -603, -585, -568, -552, -536, -520, -504, -489, -474, -459,
+ -444, -430, -416, -402, -388, -375, -361, -348, -335, -323,
+ -310, -298, -286, -274, -262, -250, -239, -228, -216, -205,
+ -194, -184, -173, -162, -152, -142, -132, -121, -112, -102,
+ -92, -82, -73, -64, -54, -45, -36, -27, -18, -9,
+ 0
+ };
+ int16_t i;
+
+ for(i = 0; i < 101; i++)
+ {
+ if(level <= LevelArray[i])
+ break;
+ }
+ return i;
+}
+
+//----------------------------------------------------------------------------
+// ReverbConvertHFLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Convert level from OpenSL ES format to LVM format
+//
+// Inputs:
+// level level to be applied
+//
+//----------------------------------------------------------------------------
+
+int16_t ReverbConvertHfLevel(int16_t Hflevel){
+ int16_t i;
+
+ static LPFPair_t LPFArray[97] =
+ { // Limit range to 50 for LVREV parameter range
+ {-10000, 50}, { -5000, 50 }, { -4000, 50}, { -3000, 158}, { -2000, 502},
+ {-1000, 1666},{ -900, 1897}, { -800, 2169}, { -700, 2496}, { -600, 2895},
+ {-500, 3400}, { -400, 4066}, { -300, 5011}, { -200, 6537}, { -100, 9826},
+ {-99, 9881 }, { -98, 9937 }, { -97, 9994 }, { -96, 10052}, { -95, 10111},
+ {-94, 10171}, { -93, 10231}, { -92, 10293}, { -91, 10356}, { -90, 10419},
+ {-89, 10484}, { -88, 10549}, { -87, 10616}, { -86, 10684}, { -85, 10753},
+ {-84, 10823}, { -83, 10895}, { -82, 10968}, { -81, 11042}, { -80, 11117},
+ {-79, 11194}, { -78, 11272}, { -77, 11352}, { -76, 11433}, { -75, 11516},
+ {-74, 11600}, { -73, 11686}, { -72, 11774}, { -71, 11864}, { -70, 11955},
+ {-69, 12049}, { -68, 12144}, { -67, 12242}, { -66, 12341}, { -65, 12443},
+ {-64, 12548}, { -63, 12654}, { -62, 12763}, { -61, 12875}, { -60, 12990},
+ {-59, 13107}, { -58, 13227}, { -57, 13351}, { -56, 13477}, { -55, 13607},
+ {-54, 13741}, { -53, 13878}, { -52, 14019}, { -51, 14164}, { -50, 14313},
+ {-49, 14467}, { -48, 14626}, { -47, 14789}, { -46, 14958}, { -45, 15132},
+ {-44, 15312}, { -43, 15498}, { -42, 15691}, { -41, 15890}, { -40, 16097},
+ {-39, 16311}, { -38, 16534}, { -37, 16766}, { -36, 17007}, { -35, 17259},
+ {-34, 17521}, { -33, 17795}, { -32, 18081}, { -31, 18381}, { -30, 18696},
+ {-29, 19027}, { -28, 19375}, { -27, 19742}, { -26, 20129}, { -25, 20540},
+ {-24, 20976}, { -23, 21439}, { -22, 21934}, { -21, 22463}, { -20, 23031},
+ {-19, 23643}, { -18, 23999}
+ };
+
+ for(i = 0; i < 96; i++)
+ {
+ if(Hflevel <= LPFArray[i].Room_HF)
+ break;
+ }
+ return LPFArray[i].LPF;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetRoomHfLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the HF level to the Reverb. Must first be converted to LVM format
+//
+// Inputs:
+// pContext: effect engine context
+// level level to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetRoomHfLevel(ReverbContext *pContext, int16_t level){
+ //LOGV("\tReverbSetRoomHfLevel start (%d)", level);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetRoomHfLevel")
+ //LOGV("\tReverbSetRoomHfLevel Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbSetRoomHfLevel() just Got -> %d\n", ActiveParams.LPF);
+
+ ActiveParams.LPF = ReverbConvertHfLevel(level);
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetRoomHfLevel")
+ //LOGV("\tReverbSetRoomhfLevel() just Set -> %d\n", ActiveParams.LPF);
+ pContext->SavedHfLevel = level;
+ //LOGV("\tReverbSetHfRoomLevel end.. saving %d", pContext->SavedHfLevel);
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetRoomHfLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the level applied to the Revervb. Must first be converted to LVM format
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int16_t ReverbGetRoomHfLevel(ReverbContext *pContext){
+ int16_t level;
+ //LOGV("\tReverbGetRoomHfLevel start, saved level is %d", pContext->SavedHfLevel);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetRoomHfLevel")
+ //LOGV("\tReverbGetRoomHfLevel Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbGetRoomHfLevel() just Got -> %d\n", ActiveParams.LPF);
+
+ level = ReverbConvertHfLevel(pContext->SavedHfLevel);
+
+ //LOGV("\tReverbGetRoomHfLevel() ActiveParams.LPFL %d, pContext->SavedHfLevel: %d, "
+ // "converted level: %d\n", ActiveParams.LPF, pContext->SavedHfLevel, level);
+
+ if(ActiveParams.LPF != level){
+ LOGV("\tLVM_ERROR : (ignore at start up) ReverbGetRoomHfLevel() has wrong level -> %d %d\n",
+ ActiveParams.Level, level);
+ }
+
+ //LOGV("\tReverbGetRoomHfLevel end");
+ return pContext->SavedHfLevel;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetReverbLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the level to the Reverb. Must first be converted to LVM format
+//
+// Inputs:
+// pContext: effect engine context
+// level level to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetReverbLevel(ReverbContext *pContext, int16_t level){
+ //LOGV("\n\tReverbSetReverbLevel start (%d)", level);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVM_INT32 CombinedLevel; // Sum of room and reverb level controls
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetReverbLevel")
+ //LOGV("\tReverbSetReverbLevel Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbSetReverbLevel just Got -> %d\n", ActiveParams.Level);
+
+ // needs to subtract max levels for both RoomLevel and ReverbLevel
+ CombinedLevel = (level + pContext->SavedRoomLevel)-LVREV_MAX_REVERB_LEVEL;
+ //LOGV("\tReverbSetReverbLevel() CombinedLevel is %d = %d + %d\n",
+ // CombinedLevel, level, pContext->SavedRoomLevel);
+
+ ActiveParams.Level = ReverbConvertLevel(CombinedLevel);
+
+ //LOGV("\tReverbSetReverbLevel() Trying to set -> %d\n", ActiveParams.Level);
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetReverbLevel")
+ //LOGV("\tReverbSetReverbLevel() just Set -> %d\n", ActiveParams.Level);
+
+ pContext->SavedReverbLevel = level;
+ //LOGV("\tReverbSetReverbLevel end pContext->SavedReverbLevel is %d\n\n",
+ // pContext->SavedReverbLevel);
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetReverbLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the level applied to the Revervb. Must first be converted to LVM format
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int16_t ReverbGetReverbLevel(ReverbContext *pContext){
+ int16_t level;
+ //LOGV("\tReverbGetReverbLevel start");
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVM_INT32 CombinedLevel; // Sum of room and reverb level controls
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetReverbLevel")
+ //LOGV("\tReverbGetReverbLevel Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbGetReverbLevel() just Got -> %d\n", ActiveParams.Level);
+
+ // needs to subtract max levels for both RoomLevel and ReverbLevel
+ CombinedLevel = (pContext->SavedReverbLevel + pContext->SavedRoomLevel)-LVREV_MAX_REVERB_LEVEL;
+
+ //LOGV("\tReverbGetReverbLevel() CombinedLevel is %d = %d + %d\n",
+ //CombinedLevel, pContext->SavedReverbLevel, pContext->SavedRoomLevel);
+ level = ReverbConvertLevel(CombinedLevel);
+
+ //LOGV("\tReverbGetReverbLevel(): ActiveParams.Level: %d, pContext->SavedReverbLevel: %d, "
+ //"pContext->SavedRoomLevel: %d, CombinedLevel: %d, converted level: %d\n",
+ //ActiveParams.Level, pContext->SavedReverbLevel,pContext->SavedRoomLevel, CombinedLevel,level);
+
+ if(ActiveParams.Level != level){
+ LOGV("\tLVM_ERROR : (ignore at start up) ReverbGetReverbLevel() has wrong level -> %d %d\n",
+ ActiveParams.Level, level);
+ }
+
+ //LOGV("\tReverbGetReverbLevel end\n");
+
+ return pContext->SavedReverbLevel;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetRoomLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the level to the Reverb. Must first be converted to LVM format
+//
+// Inputs:
+// pContext: effect engine context
+// level level to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetRoomLevel(ReverbContext *pContext, int16_t level){
+ //LOGV("\tReverbSetRoomLevel start (%d)", level);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVM_INT32 CombinedLevel; // Sum of room and reverb level controls
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetRoomLevel")
+ //LOGV("\tReverbSetRoomLevel Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbSetRoomLevel() just Got -> %d\n", ActiveParams.Level);
+
+ // needs to subtract max levels for both RoomLevel and ReverbLevel
+ CombinedLevel = (level + pContext->SavedReverbLevel)-LVREV_MAX_REVERB_LEVEL;
+ ActiveParams.Level = ReverbConvertLevel(CombinedLevel);
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetRoomLevel")
+ //LOGV("\tReverbSetRoomLevel() just Set -> %d\n", ActiveParams.Level);
+
+ pContext->SavedRoomLevel = level;
+ //LOGV("\tReverbSetRoomLevel end");
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetRoomLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the level applied to the Revervb. Must first be converted to LVM format
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int16_t ReverbGetRoomLevel(ReverbContext *pContext){
+ int16_t level;
+ //LOGV("\tReverbGetRoomLevel start");
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVM_INT32 CombinedLevel; // Sum of room and reverb level controls
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetRoomLevel")
+ //LOGV("\tReverbGetRoomLevel Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbGetRoomLevel() just Got -> %d\n", ActiveParams.Level);
+
+ // needs to subtract max levels for both RoomLevel and ReverbLevel
+ CombinedLevel = (pContext->SavedRoomLevel + pContext->SavedReverbLevel-LVREV_MAX_REVERB_LEVEL);
+ level = ReverbConvertLevel(CombinedLevel);
+
+ //LOGV("\tReverbGetRoomLevel, Level = %d, pContext->SavedRoomLevel = %d, "
+ // "pContext->SavedReverbLevel = %d, CombinedLevel = %d, level = %d",
+ //ActiveParams.Level, pContext->SavedRoomLevel, pContext->SavedReverbLevel, CombinedLevel, level);
+
+ if(ActiveParams.Level != level){
+ LOGV("\tLVM_ERROR : (ignore at start up) ReverbGetRoomLevel() has wrong level -> %d %d\n",
+ ActiveParams.Level, level);
+ }
+
+ //LOGV("\tReverbGetRoomLevel end");
+ return pContext->SavedRoomLevel;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetDecayTime()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the decay time to the Reverb.
+//
+// Inputs:
+// pContext: effect engine context
+// time decay to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetDecayTime(ReverbContext *pContext, uint32_t time){
+ //LOGV("\tReverbSetDecayTime start (%d)", time);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetDecayTime")
+ //LOGV("\tReverbSetDecayTime Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbSetDecayTime() just Got -> %d\n", ActiveParams.T60);
+
+ if (time <= LVREV_MAX_T60) {
+ ActiveParams.T60 = time;
+ }
+ else {
+ ActiveParams.T60 = LVREV_MAX_T60;
+ }
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetDecayTime")
+ //LOGV("\tReverbSetDecayTime() just Set -> %d\n", ActiveParams.T60);
+
+ pContext->SavedDecayTime = time;
+ //LOGV("\tReverbSetDecayTime end");
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetDecayTime()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the decay time applied to the Revervb.
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int32_t ReverbGetDecayTime(ReverbContext *pContext){
+ //LOGV("\tReverbGetDecayTime start");
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetDecayTime")
+ //LOGV("\tReverbGetDecayTime Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbGetDecayTime() just Got -> %d\n", ActiveParams.T60);
+
+ if(ActiveParams.T60 != pContext->SavedDecayTime){
+ // This will fail if the decay time is set to more than 7000
+ LOGV("\tLVM_ERROR : ReverbGetDecayTime() has wrong level -> %d %d\n",
+ ActiveParams.T60, pContext->SavedDecayTime);
+ }
+
+ //LOGV("\tReverbGetDecayTime end");
+ return ActiveParams.T60;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetDecayHfRatio()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the HF decay ratio to the Reverb.
+//
+// Inputs:
+// pContext: effect engine context
+// ratio ratio to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetDecayHfRatio(ReverbContext *pContext, int16_t ratio){
+ //LOGV("\tReverbSetDecayHfRatioe start (%d)", ratio);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetDecayHfRatio")
+ //LOGV("\tReverbSetDecayHfRatio Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbSetDecayHfRatio() just Got -> %d\n", ActiveParams.Damping);
+
+ ActiveParams.Damping = (LVM_INT16)(ratio/10);
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetDecayHfRatio")
+ //LOGV("\tReverbSetDecayHfRatio() just Set -> %d\n", ActiveParams.Damping);
+
+ pContext->SavedDecayHfRatio = ratio;
+ //LOGV("\tReverbSetDecayHfRatio end");
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetDecayHfRatio()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the HF decay ratio applied to the Revervb.
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int32_t ReverbGetDecayHfRatio(ReverbContext *pContext){
+ //LOGV("\tReverbGetDecayHfRatio start");
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetDecayHfRatio")
+ //LOGV("\tReverbGetDecayHfRatio Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbGetDecayHfRatio() just Got -> %d\n", ActiveParams.Damping);
+
+ if(ActiveParams.Damping != (LVM_INT16)(pContext->SavedDecayHfRatio / 10)){
+ LOGV("\tLVM_ERROR : ReverbGetDecayHfRatio() has wrong level -> %d %d\n",
+ ActiveParams.Damping, pContext->SavedDecayHfRatio);
+ }
+
+ //LOGV("\tReverbGetDecayHfRatio end");
+ return pContext->SavedDecayHfRatio;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetDiffusion()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the diffusion to the Reverb.
+//
+// Inputs:
+// pContext: effect engine context
+// level decay to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetDiffusion(ReverbContext *pContext, int16_t level){
+ //LOGV("\tReverbSetDiffusion start (%d)", level);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetDiffusion")
+ //LOGV("\tReverbSetDiffusion Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbSetDiffusion() just Got -> %d\n", ActiveParams.Density);
+
+ ActiveParams.Density = (LVM_INT16)(level/10);
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetDiffusion")
+ //LOGV("\tReverbSetDiffusion() just Set -> %d\n", ActiveParams.Density);
+
+ pContext->SavedDiffusion = level;
+ //LOGV("\tReverbSetDiffusion end");
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetDiffusion()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the decay time applied to the Revervb.
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int32_t ReverbGetDiffusion(ReverbContext *pContext){
+ //LOGV("\tReverbGetDiffusion start");
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVM_INT16 Temp;
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetDiffusion")
+ //LOGV("\tReverbGetDiffusion Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbGetDiffusion just Got -> %d\n", ActiveParams.Density);
+
+ Temp = (LVM_INT16)(pContext->SavedDiffusion/10);
+
+ if(ActiveParams.Density != Temp){
+ LOGV("\tLVM_ERROR : ReverbGetDiffusion invalid value %d %d", Temp, ActiveParams.Density);
+ }
+
+ //LOGV("\tReverbGetDiffusion end");
+ return pContext->SavedDiffusion;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetDensity()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the density level the Reverb.
+//
+// Inputs:
+// pContext: effect engine context
+// level decay to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetDensity(ReverbContext *pContext, int16_t level){
+ //LOGV("\tReverbSetDensity start (%d)", level);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetDensity")
+ //LOGV("\tReverbSetDensity Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbSetDensity just Got -> %d\n", ActiveParams.RoomSize);
+
+ ActiveParams.RoomSize = (LVM_INT16)(((level * 99) / 1000) + 1);
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetDensity")
+ //LOGV("\tReverbSetDensity just Set -> %d\n", ActiveParams.RoomSize);
+
+ pContext->SavedDensity = level;
+ //LOGV("\tReverbSetDensity end");
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetDensity()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the density level applied to the Revervb.
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int32_t ReverbGetDensity(ReverbContext *pContext){
+ //LOGV("\tReverbGetDensity start");
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVM_INT16 Temp;
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetDensity")
+ //LOGV("\tReverbGetDensity Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tReverbGetDensity() just Got -> %d\n", ActiveParams.RoomSize);
+
+
+ Temp = (LVM_INT16)(((pContext->SavedDensity * 99) / 1000) + 1);
+
+ if(Temp != ActiveParams.RoomSize){
+ LOGV("\tLVM_ERROR : ReverbGetDensity invalid value %d %d", Temp, ActiveParams.RoomSize);
+ }
+
+ //LOGV("\tReverbGetDensity end");
+ return pContext->SavedDensity;
+}
+
+//----------------------------------------------------------------------------
+// Reverb_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a Reverb parameter
+//
+// Inputs:
+// pContext - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to variable to hold retrieved value
+// pValueSize - pointer to value size: maximum size as input
+//
+// Outputs:
+// *pValue updated with parameter value
+// *pValueSize updated with actual value size
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int Reverb_getParameter(ReverbContext *pContext,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue){
+ int status = 0;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
+ char *name;
+ t_reverb_settings *pProperties;
+
+ //LOGV("\tReverb_getParameter start");
+
+ switch (param){
+ case REVERB_PARAM_ROOM_LEVEL:
+ if (*pValueSize != sizeof(int16_t)){
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize1 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_ROOM_HF_LEVEL:
+ if (*pValueSize != sizeof(int16_t)){
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize12 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_DECAY_TIME:
+ if (*pValueSize != sizeof(uint32_t)){
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize3 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(uint32_t);
+ break;
+ case REVERB_PARAM_DECAY_HF_RATIO:
+ if (*pValueSize != sizeof(int16_t)){
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize4 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_REFLECTIONS_LEVEL:
+ if (*pValueSize != sizeof(int16_t)){
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize5 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_REFLECTIONS_DELAY:
+ if (*pValueSize != sizeof(uint32_t)){
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize6 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(uint32_t);
+ break;
+ case REVERB_PARAM_REVERB_LEVEL:
+ if (*pValueSize != sizeof(int16_t)){
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize7 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_REVERB_DELAY:
+ if (*pValueSize != sizeof(uint32_t)){
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize8 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(uint32_t);
+ break;
+ case REVERB_PARAM_DIFFUSION:
+ if (*pValueSize != sizeof(int16_t)){
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize9 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_DENSITY:
+ if (*pValueSize != sizeof(int16_t)){
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize10 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_PROPERTIES:
+ if (*pValueSize != sizeof(t_reverb_settings)){
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize11 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(t_reverb_settings);
+ break;
+
+ default:
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid param %d", param);
+ return -EINVAL;
+ }
+
+ pProperties = (t_reverb_settings *) pValue;
+
+ switch (param){
+ case REVERB_PARAM_PROPERTIES:
+ pProperties->roomLevel = ReverbGetRoomLevel(pContext);
+ pProperties->roomHFLevel = ReverbGetRoomHfLevel(pContext);
+ pProperties->decayTime = ReverbGetDecayTime(pContext);
+ pProperties->decayHFRatio = ReverbGetDecayHfRatio(pContext);
+ pProperties->reflectionsLevel = 0;
+ pProperties->reflectionsDelay = 0;
+ pProperties->reverbDelay = 0;
+ pProperties->reverbLevel = ReverbGetReverbLevel(pContext);
+ pProperties->diffusion = ReverbGetDiffusion(pContext);
+ pProperties->density = ReverbGetDensity(pContext);
+
+ LOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is roomLevel %d",
+ pProperties->roomLevel);
+ LOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is roomHFLevel %d",
+ pProperties->roomHFLevel);
+ LOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is decayTime %d",
+ pProperties->decayTime);
+ LOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is decayHFRatio %d",
+ pProperties->decayHFRatio);
+ LOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is reflectionsLevel %d",
+ pProperties->reflectionsLevel);
+ LOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is reflectionsDelay %d",
+ pProperties->reflectionsDelay);
+ LOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is reverbDelay %d",
+ pProperties->reverbDelay);
+ LOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is reverbLevel %d",
+ pProperties->reverbLevel);
+ LOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is diffusion %d",
+ pProperties->diffusion);
+ LOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is density %d",
+ pProperties->density);
+ break;
+
+ case REVERB_PARAM_ROOM_LEVEL:
+ *(int16_t *)pValue = ReverbGetRoomLevel(pContext);
+
+ //LOGV("\tReverb_getParameter() REVERB_PARAM_ROOM_LEVEL Value is %d",
+ // *(int16_t *)pValue);
+ break;
+ case REVERB_PARAM_ROOM_HF_LEVEL:
+ *(int16_t *)pValue = ReverbGetRoomHfLevel(pContext);
+
+ //LOGV("\tReverb_getParameter() REVERB_PARAM_ROOM_HF_LEVEL Value is %d",
+ // *(int16_t *)pValue);
+ break;
+ case REVERB_PARAM_DECAY_TIME:
+ *(int32_t *)pValue = ReverbGetDecayTime(pContext);
+
+ //LOGV("\tReverb_getParameter() REVERB_PARAM_DECAY_TIME Value is %d",
+ // *(int32_t *)pValue);
+ break;
+ case REVERB_PARAM_DECAY_HF_RATIO:
+ *(int16_t *)pValue = ReverbGetDecayHfRatio(pContext);
+
+ //LOGV("\tReverb_getParameter() REVERB_PARAM_DECAY_HF_RATION Value is %d",
+ // *(int16_t *)pValue);
+ break;
+ case REVERB_PARAM_REVERB_LEVEL:
+ *(int16_t *)pValue = ReverbGetReverbLevel(pContext);
+
+ //LOGV("\tReverb_getParameter() REVERB_PARAM_REVERB_LEVEL Value is %d",
+ // *(int16_t *)pValue);
+ break;
+ case REVERB_PARAM_DIFFUSION:
+ *(int16_t *)pValue = ReverbGetDiffusion(pContext);
+
+ //LOGV("\tReverb_getParameter() REVERB_PARAM_DECAY_DIFFUSION Value is %d",
+ // *(int16_t *)pValue);
+ break;
+ case REVERB_PARAM_DENSITY:
+ *(uint16_t *)pValue = 0;
+ *(int16_t *)pValue = ReverbGetDensity(pContext);
+ //LOGV("\tReverb_getParameter() REVERB_PARAM_DENSITY Value is %d",
+ // *(uint32_t *)pValue);
+ break;
+ case REVERB_PARAM_REFLECTIONS_LEVEL:
+ *(uint16_t *)pValue = 0;
+ case REVERB_PARAM_REFLECTIONS_DELAY:
+ *(uint32_t *)pValue = 0;
+ case REVERB_PARAM_REVERB_DELAY:
+ *(uint32_t *)pValue = 0;
+ break;
+
+ default:
+ LOGV("\tLVM_ERROR : Reverb_getParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ //LOGV("\tReverb_getParameter end");
+ return status;
+} /* end Reverb_getParameter */
+
+//----------------------------------------------------------------------------
+// Reverb_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a Reverb parameter
+//
+// Inputs:
+// pContext - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to value
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue){
+ int status = 0;
+ int16_t level;
+ uint32_t time;
+ t_reverb_settings *pProperties;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
+
+ //LOGV("\tReverb_setParameter start");
+
+ switch (param){
+ case REVERB_PARAM_PROPERTIES:
+ LOGV("\tReverb_setParameter() REVERB_PARAM_PROPERTIES");
+ pProperties = (t_reverb_settings *) pValue;
+ ReverbSetRoomLevel(pContext, pProperties->roomLevel);
+ ReverbSetRoomHfLevel(pContext, pProperties->roomHFLevel);
+ ReverbSetDecayTime(pContext, pProperties->decayTime);
+ ReverbSetDecayHfRatio(pContext, pProperties->decayHFRatio);
+ ReverbSetReverbLevel(pContext, pProperties->reverbLevel);
+ ReverbSetDiffusion(pContext, pProperties->diffusion);
+ ReverbSetDensity(pContext, pProperties->density);
+ break;
+ case REVERB_PARAM_ROOM_LEVEL:
+ level = *(int16_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_ROOM_LEVEL value is %d", level);
+ //LOGV("\tReverb_setParameter() Calling ReverbSetRoomLevel");
+ ReverbSetRoomLevel(pContext, level);
+ //LOGV("\tReverb_setParameter() Called ReverbSetRoomLevel");
+ break;
+ case REVERB_PARAM_ROOM_HF_LEVEL:
+ level = *(int16_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_ROOM_HF_LEVEL value is %d", level);
+ //LOGV("\tReverb_setParameter() Calling ReverbSetRoomHfLevel");
+ ReverbSetRoomHfLevel(pContext, level);
+ //LOGV("\tReverb_setParameter() Called ReverbSetRoomHfLevel");
+ break;
+ case REVERB_PARAM_DECAY_TIME:
+ time = *(uint32_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_TIME value is %d", time);
+ //LOGV("\tReverb_setParameter() Calling ReverbSetDecayTime");
+ ReverbSetDecayTime(pContext, time);
+ //LOGV("\tReverb_setParameter() Called ReverbSetDecayTime");
+ break;
+ case REVERB_PARAM_DECAY_HF_RATIO:
+ time = *(int16_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_HF_RATIO value is %d", time);
+ //LOGV("\tReverb_setParameter() Calling ReverbSetDecayHfRatio");
+ ReverbSetDecayHfRatio(pContext, time);
+ //LOGV("\tReverb_setParameter() Called ReverbSetDecayHfRatio");
+ break;
+ case REVERB_PARAM_REVERB_LEVEL:
+ level = *(int16_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_REVERB_LEVEL value is %d", level);
+ //LOGV("\tReverb_setParameter() Calling ReverbSetReverbLevel");
+ ReverbSetReverbLevel(pContext, level);
+ //LOGV("\tReverb_setParameter() Called ReverbSetReverbLevel");
+ break;
+ case REVERB_PARAM_DIFFUSION:
+ time = *(int16_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DIFFUSION value is %d", time);
+ //LOGV("\tReverb_setParameter() Calling ReverbSetDiffusion");
+ ReverbSetDiffusion(pContext, time);
+ //LOGV("\tReverb_setParameter() Called ReverbSetDiffusion");
+ break;
+ case REVERB_PARAM_DENSITY:
+ time = *(int16_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DENSITY value is %d", time);
+ //LOGV("\tReverb_setParameter() Calling ReverbSetDensity");
+ ReverbSetDensity(pContext, time);
+ //LOGV("\tReverb_setParameter() Called ReverbSetDensity");
+ break;
+ break;
+ case REVERB_PARAM_REFLECTIONS_LEVEL:
+ case REVERB_PARAM_REFLECTIONS_DELAY:
+ case REVERB_PARAM_REVERB_DELAY:
+ break;
+ default:
+ LOGV("\tLVM_ERROR : Reverb_setParameter() invalid param %d", param);
+ break;
+ }
+
+ //LOGV("\tReverb_setParameter end");
+ return status;
+} /* end Reverb_setParameter */
+
+} // namespace
+} // namespace
+
+/* Effect Control Interface Implementation: Process */
+extern "C" int Reverb_process(effect_interface_t self,
+ audio_buffer_t *inBuffer,
+ audio_buffer_t *outBuffer){
+ android::ReverbContext * pContext = (android::ReverbContext *) self;
+ int status = 0;
+
+ if (pContext == NULL){
+ LOGV("\tLVM_ERROR : Reverb_process() ERROR pContext == NULL");
+ return -EINVAL;
+ }
+ if (inBuffer == NULL || inBuffer->raw == NULL ||
+ outBuffer == NULL || outBuffer->raw == NULL ||
+ inBuffer->frameCount != outBuffer->frameCount){
+ LOGV("\tLVM_ERROR : Reverb_process() ERROR NULL INPUT POINTER OR FRAME COUNT IS WRONG");
+ return -EINVAL;
+ }
+ if (pContext->bEnabled == LVM_FALSE){
+ LOGV("\tReverb_process() ERROR Effect is not enabled");
+ return -ENODATA;
+ }
+ //LOGV("\tReverb_process() Calling process with %d frames", outBuffer->frameCount);
+ /* Process all the available frames, block processing is handled internalLY by the LVM bundle */
+ status = process( (LVM_INT16 *)inBuffer->raw,
+ (LVM_INT16 *)outBuffer->raw,
+ outBuffer->frameCount,
+ pContext);
+
+ return status;
+} /* end Reverb_process */
+
+/* Effect Control Interface Implementation: Command */
+extern "C" int Reverb_command(effect_interface_t self,
+ uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData){
+ android::ReverbContext * pContext = (android::ReverbContext *) self;
+ int retsize;
+
+ if (pContext == NULL){
+ LOGV("\tLVM_ERROR : Reverb_command ERROR pContext == NULL");
+ return -EINVAL;
+ }
+
+ //LOGV("\tReverb_command INPUTS are: command %d cmdSize %d",cmdCode, cmdSize);
+
+ switch (cmdCode){
+ case EFFECT_CMD_INIT:
+ //LOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_INIT start");
+
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ LOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_INIT: ERROR");
+ return -EINVAL;
+ }
+ *(int *) pReplyData = 0;
+ break;
+
+ case EFFECT_CMD_CONFIGURE:
+ //LOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_CONFIGURE start");
+ if (pCmdData == NULL||
+ cmdSize != sizeof(effect_config_t)||
+ pReplyData == NULL||
+ *replySize != sizeof(int)){
+ LOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_CONFIGURE: ERROR");
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Reverb_configure(pContext, (effect_config_t *) pCmdData);
+ break;
+
+ case EFFECT_CMD_RESET:
+ //LOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_RESET start");
+ Reverb_configure(pContext, &pContext->config);
+ break;
+
+ case EFFECT_CMD_GET_PARAM:{
+ //LOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_GET_PARAM start");
+ if (pCmdData == NULL ||
+ cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+ pReplyData == NULL ||
+ *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){
+ LOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_GET_PARAM: ERROR");
+ return -EINVAL;
+ }
+ effect_param_t *p = (effect_param_t *)pCmdData;
+
+ memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+
+ p = (effect_param_t *)pReplyData;
+
+ int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+
+ p->status = android::Reverb_getParameter(pContext,
+ (void *)p->data,
+ (size_t *)&p->vsize,
+ p->data + voffset);
+
+ *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+ //LOGV("\tReverb_command EFFECT_CMD_GET_PARAM "
+ // "*pCmdData %d, *replySize %d, *pReplyData %d ",
+ // *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+ // *replySize,
+ // *(int16_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset));
+
+ } break;
+ case EFFECT_CMD_SET_PARAM:{
+
+ //LOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_SET_PARAM start");
+ //LOGV("\tReverb_command EFFECT_CMD_SET_PARAM param %d, *replySize %d, value %d ",
+ // *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+ // *replySize,
+ // *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
+
+ if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)))
+ || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) {
+ LOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR");
+ return -EINVAL;
+ }
+
+ effect_param_t *p = (effect_param_t *) pCmdData;
+
+ if (p->psize != sizeof(int32_t)){
+ LOGV("\t4LVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
+ return -EINVAL;
+ }
+
+ //LOGV("\tn5Reverb_command cmdSize is %d\n"
+ // "\tsizeof(effect_param_t) is %d\n"
+ // "\tp->psize is %d\n"
+ // "\tp->vsize is %d"
+ // "\n",
+ // cmdSize, sizeof(effect_param_t), p->psize, p->vsize );
+
+ *(int *)pReplyData = android::Reverb_setParameter(pContext,
+ (void *)p->data,
+ p->data + p->psize);
+ } break;
+
+ case EFFECT_CMD_ENABLE:
+ //LOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_ENABLE start");
+
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ LOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_ENABLE: ERROR");
+ return -EINVAL;
+ }
+ if(pContext->bEnabled == LVM_TRUE){
+ LOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
+ return -EINVAL;
+ }
+ *(int *)pReplyData = 0;
+ pContext->bEnabled = LVM_TRUE;
+ break;
+ case EFFECT_CMD_DISABLE:
+ //LOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_DISABLE start");
+
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ LOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_DISABLE: ERROR");
+ return -EINVAL;
+ }
+ if(pContext->bEnabled == LVM_FALSE){
+ LOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
+ return -EINVAL;
+ }
+ *(int *)pReplyData = 0;
+ pContext->bEnabled = LVM_FALSE;
+ break;
+
+ case EFFECT_CMD_SET_DEVICE:
+ case EFFECT_CMD_SET_VOLUME:
+ case EFFECT_CMD_SET_AUDIO_MODE:
+ //LOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_SET_DEVICE/EFFECT_CMD_SET_VOLUME/EFFECT_CMD_SET_AUDIO_MODE start");
+ break;
+
+ default:
+ LOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "DEFAULT start %d ERROR",cmdCode);
+ return -EINVAL;
+ }
+
+ //LOGV("\tReverb_command end\n\n");
+ return 0;
+} /* end Reverb_command */
+
+// effect_interface_t interface implementation for Reverb effect
+const struct effect_interface_s gReverbInterface = {
+ Reverb_process,
+ Reverb_command
+}; /* end gReverbInterface */
+
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h
new file mode 100755
index 0000000..1ab423f
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_EFFECTREVERB_H_
+#define ANDROID_EFFECTREVERB_H_
+
+#include <media/EffectEnvironmentalReverbApi.h>
+#include <media/EffectPresetReverbApi.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct _LPFPair_t
+{
+ int16_t Room_HF;
+ int16_t LPF;
+} LPFPair_t;
+#if __cplusplus
+} // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTREVERB_H_*/
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 977e6be..b4d01f5 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -31,7 +31,8 @@
IEffect.cpp \
IEffectClient.cpp \
AudioEffect.cpp \
- Visualizer.cpp
+ Visualizer.cpp \
+ fixedfft.cpp.arm
LOCAL_SHARED_LIBRARIES := \
libui libcutils libutils libbinder libsonivox libicuuc libexpat libsurfaceflinger_client libcamera_client
@@ -50,11 +51,7 @@
$(JNI_H_INCLUDE) \
$(call include-path-for, graphics corecg) \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
- external/speex/include \
- external/speex/libspeex \
external/icu4c/common \
external/expat/lib
-LOCAL_STATIC_LIBRARIES := libspeex
-
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 0f55b19d..9dfdcb0 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -22,12 +22,14 @@
#include <media/IMediaPlayer.h>
#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/Surface.h>
namespace android {
enum {
DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
SET_VIDEO_SURFACE,
+ SET_VIDEO_ISURFACE,
PREPARE_ASYNC,
START,
STOP,
@@ -65,11 +67,20 @@
remote()->transact(DISCONNECT, data, &reply);
}
- status_t setVideoSurface(const sp<ISurface>& surface)
+ status_t setVideoISurface(const sp<ISurface>& surface)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
data.writeStrongBinder(surface->asBinder());
+ remote()->transact(SET_VIDEO_ISURFACE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setVideoSurface(const sp<Surface>& surface)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ Surface::writeToParcel(surface, &data);
remote()->transact(SET_VIDEO_SURFACE, data, &reply);
return reply.readInt32();
}
@@ -256,9 +267,15 @@
disconnect();
return NO_ERROR;
} break;
- case SET_VIDEO_SURFACE: {
+ case SET_VIDEO_ISURFACE: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder());
+ reply->writeInt32(setVideoISurface(surface));
+ return NO_ERROR;
+ } break;
+ case SET_VIDEO_SURFACE: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ sp<Surface> surface = Surface::readFromParcel(data);
reply->writeInt32(setVideoSurface(surface));
return NO_ERROR;
} break;
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 947ff34..f55a01e 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -19,7 +19,7 @@
#define LOG_TAG "IMediaRecorder"
#include <utils/Log.h>
#include <binder/Parcel.h>
-#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/Surface.h>
#include <camera/ICamera.h>
#include <media/IMediaRecorderClient.h>
#include <media/IMediaRecorder.h>
@@ -69,12 +69,12 @@
return reply.readInt32();
}
- status_t setPreviewSurface(const sp<ISurface>& surface)
+ status_t setPreviewSurface(const sp<Surface>& surface)
{
LOGV("setPreviewSurface(%p)", surface.get());
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
- data.writeStrongBinder(surface->asBinder());
+ Surface::writeToParcel(surface, &data);
remote()->transact(SET_PREVIEW_SURFACE, data, &reply);
return reply.readInt32();
}
@@ -409,7 +409,7 @@
case SET_PREVIEW_SURFACE: {
LOGV("SET_PREVIEW_SURFACE");
CHECK_INTERFACE(IMediaRecorder, data, reply);
- sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder());
+ sp<Surface> surface = Surface::readFromParcel(data);
reply->writeInt32(setPreviewSurface(surface));
return NO_ERROR;
} break;
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
index 32cdb49..39552b6 100644
--- a/media/libmedia/Visualizer.cpp
+++ b/media/libmedia/Visualizer.cpp
@@ -26,10 +26,7 @@
#include <media/Visualizer.h>
-extern "C" {
-#define FLOATING_POINT 1
-#include "fftwrap.h"
-}
+extern void fixed_fft_real(int n, int32_t *v);
namespace android {
@@ -47,18 +44,10 @@
mCaptureCbkUser(NULL)
{
initCaptureSize();
- if (mCaptureSize != 0) {
- mFftTable = spx_fft_init(mCaptureSize);
- } else {
- mFftTable = NULL;
- }
}
Visualizer::~Visualizer()
{
- if (mFftTable != NULL) {
- spx_fft_destroy(mFftTable);
- }
}
status_t Visualizer::setEnabled(bool enabled)
@@ -163,11 +152,6 @@
}
if (status == NO_ERROR) {
mCaptureSize = size;
- if (mFftTable != NULL) {
- spx_fft_destroy(mFftTable);
- }
- mFftTable = spx_fft_init(mCaptureSize);
- LOGV("setCaptureSize size %d mFftTable %p", mCaptureSize, mFftTable);
}
return status;
@@ -219,19 +203,24 @@
status_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform)
{
- if (mFftTable == NULL) {
- return NO_INIT;
+ int32_t workspace[mCaptureSize >> 1];
+ int32_t nonzero = 0;
+
+ for (uint32_t i = 0; i < mCaptureSize; i += 2) {
+ workspace[i >> 1] = (waveform[i] ^ 0x80) << 23;
+ workspace[i >> 1] |= (waveform[i + 1] ^ 0x80) << 7;
+ nonzero |= workspace[i >> 1];
}
- float fsrc[mCaptureSize];
- for (uint32_t i = 0; i < mCaptureSize; i++) {
- fsrc[i] = (int16_t)(waveform[i] ^ 0x80) << 8;
+ if (nonzero) {
+ fixed_fft_real(mCaptureSize >> 1, workspace);
}
- float fdst[mCaptureSize];
- spx_fft_float(mFftTable, fsrc, fdst);
- for (uint32_t i = 0; i < mCaptureSize; i++) {
- fft[i] = (uint8_t)((int32_t)fdst[i] >> 8);
+
+ for (uint32_t i = 0; i < mCaptureSize; i += 2) {
+ fft[i] = workspace[i >> 1] >> 23;
+ fft[i + 1] = workspace[i >> 1] >> 7;
}
+
return NO_ERROR;
}
diff --git a/media/libmedia/fixedfft.cpp b/media/libmedia/fixedfft.cpp
new file mode 100644
index 0000000..28eb05a
--- /dev/null
+++ b/media/libmedia/fixedfft.cpp
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+/* A Fixed point implementation of Fast Fourier Transform (FFT). Complex numbers
+ * are represented by 32-bit integers, where higher 16 bits are real part and
+ * lower ones are imaginary part. Few compromises are made between efficiency,
+ * accuracy, and maintainability. To make it fast, arithmetic shifts are used
+ * instead of divisions, and bitwise inverses are used instead of negates. To
+ * keep it small, only radix-2 Cooley-Tukey algorithm is implemented, and only
+ * half of the twiddle factors are stored. Although there are still ways to make
+ * it even faster or smaller, it costs too much on one of the aspects.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <machine/cpu-features.h>
+
+#define LOG_FFT_SIZE 10
+#define MAX_FFT_SIZE (1 << LOG_FFT_SIZE)
+
+static const int32_t twiddle[MAX_FFT_SIZE / 4] = {
+ 0x00008000, 0xff378001, 0xfe6e8002, 0xfda58006, 0xfcdc800a, 0xfc13800f,
+ 0xfb4a8016, 0xfa81801e, 0xf9b88027, 0xf8ef8032, 0xf827803e, 0xf75e804b,
+ 0xf6958059, 0xf5cd8068, 0xf5058079, 0xf43c808b, 0xf374809e, 0xf2ac80b2,
+ 0xf1e480c8, 0xf11c80de, 0xf05580f6, 0xef8d8110, 0xeec6812a, 0xedff8146,
+ 0xed388163, 0xec718181, 0xebab81a0, 0xeae481c1, 0xea1e81e2, 0xe9588205,
+ 0xe892822a, 0xe7cd824f, 0xe7078276, 0xe642829d, 0xe57d82c6, 0xe4b982f1,
+ 0xe3f4831c, 0xe3308349, 0xe26d8377, 0xe1a983a6, 0xe0e683d6, 0xe0238407,
+ 0xdf61843a, 0xde9e846e, 0xdddc84a3, 0xdd1b84d9, 0xdc598511, 0xdb998549,
+ 0xdad88583, 0xda1885be, 0xd95885fa, 0xd8988637, 0xd7d98676, 0xd71b86b6,
+ 0xd65c86f6, 0xd59e8738, 0xd4e1877b, 0xd42487c0, 0xd3678805, 0xd2ab884c,
+ 0xd1ef8894, 0xd13488dd, 0xd0798927, 0xcfbe8972, 0xcf0489be, 0xce4b8a0c,
+ 0xcd928a5a, 0xccd98aaa, 0xcc218afb, 0xcb698b4d, 0xcab28ba0, 0xc9fc8bf5,
+ 0xc9468c4a, 0xc8908ca1, 0xc7db8cf8, 0xc7278d51, 0xc6738dab, 0xc5c08e06,
+ 0xc50d8e62, 0xc45b8ebf, 0xc3a98f1d, 0xc2f88f7d, 0xc2488fdd, 0xc198903e,
+ 0xc0e990a1, 0xc03a9105, 0xbf8c9169, 0xbedf91cf, 0xbe329236, 0xbd86929e,
+ 0xbcda9307, 0xbc2f9371, 0xbb8593dc, 0xbadc9448, 0xba3394b5, 0xb98b9523,
+ 0xb8e39592, 0xb83c9603, 0xb7969674, 0xb6f196e6, 0xb64c9759, 0xb5a897ce,
+ 0xb5059843, 0xb46298b9, 0xb3c09930, 0xb31f99a9, 0xb27f9a22, 0xb1df9a9c,
+ 0xb1409b17, 0xb0a29b94, 0xb0059c11, 0xaf689c8f, 0xaecc9d0e, 0xae319d8e,
+ 0xad979e0f, 0xacfd9e91, 0xac659f14, 0xabcd9f98, 0xab36a01c, 0xaaa0a0a2,
+ 0xaa0aa129, 0xa976a1b0, 0xa8e2a238, 0xa84fa2c2, 0xa7bda34c, 0xa72ca3d7,
+ 0xa69ca463, 0xa60ca4f0, 0xa57ea57e, 0xa4f0a60c, 0xa463a69c, 0xa3d7a72c,
+ 0xa34ca7bd, 0xa2c2a84f, 0xa238a8e2, 0xa1b0a976, 0xa129aa0a, 0xa0a2aaa0,
+ 0xa01cab36, 0x9f98abcd, 0x9f14ac65, 0x9e91acfd, 0x9e0fad97, 0x9d8eae31,
+ 0x9d0eaecc, 0x9c8faf68, 0x9c11b005, 0x9b94b0a2, 0x9b17b140, 0x9a9cb1df,
+ 0x9a22b27f, 0x99a9b31f, 0x9930b3c0, 0x98b9b462, 0x9843b505, 0x97ceb5a8,
+ 0x9759b64c, 0x96e6b6f1, 0x9674b796, 0x9603b83c, 0x9592b8e3, 0x9523b98b,
+ 0x94b5ba33, 0x9448badc, 0x93dcbb85, 0x9371bc2f, 0x9307bcda, 0x929ebd86,
+ 0x9236be32, 0x91cfbedf, 0x9169bf8c, 0x9105c03a, 0x90a1c0e9, 0x903ec198,
+ 0x8fddc248, 0x8f7dc2f8, 0x8f1dc3a9, 0x8ebfc45b, 0x8e62c50d, 0x8e06c5c0,
+ 0x8dabc673, 0x8d51c727, 0x8cf8c7db, 0x8ca1c890, 0x8c4ac946, 0x8bf5c9fc,
+ 0x8ba0cab2, 0x8b4dcb69, 0x8afbcc21, 0x8aaaccd9, 0x8a5acd92, 0x8a0cce4b,
+ 0x89becf04, 0x8972cfbe, 0x8927d079, 0x88ddd134, 0x8894d1ef, 0x884cd2ab,
+ 0x8805d367, 0x87c0d424, 0x877bd4e1, 0x8738d59e, 0x86f6d65c, 0x86b6d71b,
+ 0x8676d7d9, 0x8637d898, 0x85fad958, 0x85beda18, 0x8583dad8, 0x8549db99,
+ 0x8511dc59, 0x84d9dd1b, 0x84a3dddc, 0x846ede9e, 0x843adf61, 0x8407e023,
+ 0x83d6e0e6, 0x83a6e1a9, 0x8377e26d, 0x8349e330, 0x831ce3f4, 0x82f1e4b9,
+ 0x82c6e57d, 0x829de642, 0x8276e707, 0x824fe7cd, 0x822ae892, 0x8205e958,
+ 0x81e2ea1e, 0x81c1eae4, 0x81a0ebab, 0x8181ec71, 0x8163ed38, 0x8146edff,
+ 0x812aeec6, 0x8110ef8d, 0x80f6f055, 0x80def11c, 0x80c8f1e4, 0x80b2f2ac,
+ 0x809ef374, 0x808bf43c, 0x8079f505, 0x8068f5cd, 0x8059f695, 0x804bf75e,
+ 0x803ef827, 0x8032f8ef, 0x8027f9b8, 0x801efa81, 0x8016fb4a, 0x800ffc13,
+ 0x800afcdc, 0x8006fda5, 0x8002fe6e, 0x8001ff37,
+};
+
+/* Returns the multiplication of \conj{a} and {b}. */
+static inline int32_t mult(int32_t a, int32_t b)
+{
+#if __ARM_ARCH__ >= 6
+ int32_t t = b;
+ __asm__("smuad %0, %0, %1" : "+r" (t) : "r" (a));
+ __asm__("smusdx %0, %0, %1" : "+r" (b) : "r" (a));
+ __asm__("pkhtb %0, %0, %1, ASR #16" : "+r" (t) : "r" (b));
+ return t;
+#else
+ return (((a >> 16) * (b >> 16) + (int16_t)a * (int16_t)b) & ~0xFFFF) |
+ ((((a >> 16) * (int16_t)b - (int16_t)a * (b >> 16)) >> 16) & 0xFFFF);
+#endif
+}
+
+static inline int32_t half(int32_t a)
+{
+#if __ARM_ARCH__ >= 6
+ __asm__("shadd16 %0, %0, %1" : "+r" (a) : "r" (0));
+ return a;
+#else
+ return ((a >> 1) & ~0x8000) | (a & 0x8000);
+#endif
+}
+
+void fixed_fft(int n, int32_t *v)
+{
+ int scale = LOG_FFT_SIZE, i, p, r;
+
+ for (r = 0, i = 1; i < n; ++i) {
+ for (p = n; !(p & r); p >>= 1, r ^= p);
+ if (i < r) {
+ int32_t t = v[i];
+ v[i] = v[r];
+ v[r] = t;
+ }
+ }
+
+ for (p = 1; p < n; p <<= 1) {
+ --scale;
+
+ for (i = 0; i < n; i += p << 1) {
+ int32_t x = half(v[i]);
+ int32_t y = half(v[i + p]);
+ v[i] = x + y;
+ v[i + p] = x - y;
+ }
+
+ for (r = 1; r < p; ++r) {
+ int32_t w = MAX_FFT_SIZE / 4 - (r << scale);
+ i = w >> 31;
+ w = twiddle[(w ^ i) - i] ^ (i << 16);
+ for (i = r; i < n; i += p << 1) {
+ int32_t x = half(v[i]);
+ int32_t y = mult(w, v[i + p]);
+ v[i] = x - y;
+ v[i + p] = x + y;
+ }
+ }
+ }
+}
+
+void fixed_fft_real(int n, int32_t *v)
+{
+ int scale = LOG_FFT_SIZE, m = n >> 1, i;
+
+ fixed_fft(n, v);
+ for (i = 1; i <= n; i <<= 1, --scale);
+ v[0] = mult(~v[0], 0x80008000);
+ v[m] = half(v[m]);
+
+ for (i = 1; i < n >> 1; ++i) {
+ int32_t x = half(v[i]);
+ int32_t z = half(v[n - i]);
+ int32_t y = z - (x ^ 0xFFFF);
+ x = half(x + (z ^ 0xFFFF));
+ y = mult(y, twiddle[i << scale]);
+ v[i] = x - y;
+ v[n - i] = (x + y) ^ 0xFFFF;
+ }
+}
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index f3229c0..32b20c7 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -206,10 +206,15 @@
LOGV("setVideoSurface");
Mutex::Autolock _l(mLock);
if (mPlayer == 0) return NO_INIT;
- if (surface != NULL)
- return mPlayer->setVideoSurface(surface->getISurface());
- else
- return mPlayer->setVideoSurface(NULL);
+
+ status_t err = mPlayer->setVideoISurface(
+ surface == NULL ? NULL : surface->getISurface());
+
+ if (err != OK) {
+ return err;
+ }
+
+ return mPlayer->setVideoSurface(surface);
}
// must call with lock held
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 9d53c25..7f25359 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -65,7 +65,7 @@
return INVALID_OPERATION;
}
- status_t ret = mMediaRecorder->setPreviewSurface(surface->getISurface());
+ status_t ret = mMediaRecorder->setPreviewSurface(surface);
if (OK != ret) {
LOGV("setPreviewSurface failed: %d", ret);
mCurrentState = MEDIA_RECORDER_ERROR;
@@ -643,4 +643,3 @@
}
}; // namespace android
-
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index b5972e7..d9b0c69 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -889,7 +889,15 @@
return mStatus;
}
-status_t MediaPlayerService::Client::setVideoSurface(const sp<ISurface>& surface)
+status_t MediaPlayerService::Client::setVideoISurface(const sp<ISurface>& surface)
+{
+ LOGV("[%d] setVideoISurface(%p)", mConnId, surface.get());
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ return p->setVideoISurface(surface);
+}
+
+status_t MediaPlayerService::Client::setVideoSurface(const sp<Surface>& surface)
{
LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get());
sp<MediaPlayerBase> p = getPlayer();
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index a967ee2..deb458c 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -204,7 +204,8 @@
// IMediaPlayer interface
virtual void disconnect();
- virtual status_t setVideoSurface(const sp<ISurface>& surface);
+ virtual status_t setVideoISurface(const sp<ISurface>& surface);
+ virtual status_t setVideoSurface(const sp<Surface>& surface);
virtual status_t prepareAsync();
virtual status_t start();
virtual status_t stop();
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 73862c3..7e05043 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -70,7 +70,7 @@
return mRecorder->setCamera(camera);
}
-status_t MediaRecorderClient::setPreviewSurface(const sp<ISurface>& surface)
+status_t MediaRecorderClient::setPreviewSurface(const sp<Surface>& surface)
{
LOGV("setPreviewSurface");
Mutex::Autolock lock(mLock);
@@ -337,4 +337,3 @@
}
}; // namespace android
-
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 1d1913d..6c17217 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -29,7 +29,7 @@
{
public:
virtual status_t setCamera(const sp<ICamera>& camera);
- virtual status_t setPreviewSurface(const sp<ISurface>& surface);
+ virtual status_t setPreviewSurface(const sp<Surface>& surface);
virtual status_t setVideoSource(int vs);
virtual status_t setAudioSource(int as);
virtual status_t setOutputFormat(int of);
@@ -66,4 +66,3 @@
}; // namespace android
#endif // ANDROID_MEDIARECORDERCLIENT_H
-
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index 4a60ece..06e4b70 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -35,7 +35,8 @@
const char* path, const KeyedVector<String8, String8> *headers);
virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- virtual status_t setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
+ virtual status_t setVideoISurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
+ virtual status_t setVideoSurface(const sp<Surface>& surface) { return UNKNOWN_ERROR; }
virtual status_t prepare();
virtual status_t prepareAsync();
virtual status_t start();
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index 2c96d6d..6b9bf85 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -44,13 +44,20 @@
return mPlayer->setDataSource(dup(fd), offset, length);
}
-status_t StagefrightPlayer::setVideoSurface(const sp<ISurface> &surface) {
- LOGV("setVideoSurface");
+status_t StagefrightPlayer::setVideoISurface(const sp<ISurface> &surface) {
+ LOGV("setVideoISurface");
mPlayer->setISurface(surface);
return OK;
}
+status_t StagefrightPlayer::setVideoSurface(const sp<Surface> &surface) {
+ LOGV("setVideoSurface");
+
+ mPlayer->setSurface(surface);
+ return OK;
+}
+
status_t StagefrightPlayer::prepare() {
return mPlayer->prepare();
}
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index 781eb44..dd37102 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -35,7 +35,8 @@
const char *url, const KeyedVector<String8, String8> *headers);
virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- virtual status_t setVideoSurface(const sp<ISurface> &surface);
+ virtual status_t setVideoISurface(const sp<ISurface> &surface);
+ virtual status_t setVideoSurface(const sp<Surface> &surface);
virtual status_t prepare();
virtual status_t prepareAsync();
virtual status_t start();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 59a544c..a24e56c 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -35,7 +35,7 @@
#include <camera/ICamera.h>
#include <camera/Camera.h>
#include <camera/CameraParameters.h>
-#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/Surface.h>
#include <utils/Errors.h>
#include <sys/types.h>
#include <ctype.h>
@@ -201,7 +201,7 @@
return OK;
}
-status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) {
+status_t StagefrightRecorder::setPreviewSurface(const sp<Surface> &surface) {
LOGV("setPreviewSurface: %p", surface.get());
mPreviewSurface = surface;
@@ -342,10 +342,14 @@
status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
LOGV("setParamMaxFileDurationUs: %lld us", timeUs);
- if (timeUs <= 100000LL) { // XXX: 100 milli-seconds
+ if (timeUs <= 0) {
+ LOGW("Max file duration is not positive: %lld us. Disabling duration limit.", timeUs);
+ timeUs = 0; // Disable the duration limit for zero or negative values.
+ } else if (timeUs <= 100000LL) { // XXX: 100 milli-seconds
LOGE("Max file duration is too short: %lld us", timeUs);
return BAD_VALUE;
}
+
mMaxFileDurationUs = timeUs;
return OK;
}
@@ -1235,11 +1239,19 @@
return OK;
}
-status_t StagefrightRecorder::dump(int fd, const Vector<String16>& args) const {
+status_t StagefrightRecorder::dump(
+ int fd, const Vector<String16>& args) const {
+ LOGV("dump");
const size_t SIZE = 256;
char buffer[SIZE];
String8 result;
- snprintf(buffer, SIZE, " Recorder: %p", this);
+ if (mWriter != 0) {
+ mWriter->dump(fd, args);
+ } else {
+ snprintf(buffer, SIZE, " No file writer\n");
+ result.append(buffer);
+ }
+ snprintf(buffer, SIZE, " Recorder: %p\n", this);
snprintf(buffer, SIZE, " Output file (fd %d):\n", mOutputFd);
result.append(buffer);
snprintf(buffer, SIZE, " File format: %d\n", mOutputFormat);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index a8be27d..628e19b 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -42,7 +42,7 @@
virtual status_t setVideoSize(int width, int height);
virtual status_t setVideoFrameRate(int frames_per_second);
virtual status_t setCamera(const sp<ICamera>& camera);
- virtual status_t setPreviewSurface(const sp<ISurface>& surface);
+ virtual status_t setPreviewSurface(const sp<Surface>& surface);
virtual status_t setOutputFile(const char *path);
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
virtual status_t setParameters(const String8& params);
@@ -63,7 +63,7 @@
};
sp<Camera> mCamera;
- sp<ISurface> mPreviewSurface;
+ sp<Surface> mPreviewSurface;
sp<IMediaRecorderClient> mListener;
sp<MediaWriter> mWriter;
sp<AudioSource> mAudioSourceNode;
@@ -144,4 +144,3 @@
} // namespace android
#endif // STAGEFRIGHT_RECORDER_H_
-
diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h
index 6e6c3cd..5eaf592 100644
--- a/media/libmediaplayerservice/TestPlayerStub.h
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -75,7 +75,10 @@
// All the methods below wrap the mPlayer instance.
- virtual status_t setVideoSurface(const android::sp<android::ISurface>& s) {
+ virtual status_t setVideoISurface(const android::sp<android::ISurface>& s) {
+ return mPlayer->setVideoISurface(s);
+ }
+ virtual status_t setVideoSurface(const android::sp<android::Surface>& s) {
return mPlayer->setVideoSurface(s);
}
virtual status_t prepare() {return mPlayer->prepare();}
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index f2653cf..b7beb6b 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -44,7 +44,7 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/OMXCodec.h>
-#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/Surface.h>
#include <media/stagefright/foundation/ALooper.h>
@@ -97,13 +97,14 @@
bool previewOnly,
const char *componentName,
OMX_COLOR_FORMATTYPE colorFormat,
- const sp<ISurface> &surface,
+ const sp<ISurface> &isurface,
+ const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
size_t decodedWidth, size_t decodedHeight)
: mTarget(NULL),
mLibHandle(NULL) {
init(previewOnly, componentName,
- colorFormat, surface, displayWidth,
+ colorFormat, isurface, surface, displayWidth,
displayHeight, decodedWidth, decodedHeight);
}
@@ -135,7 +136,8 @@
bool previewOnly,
const char *componentName,
OMX_COLOR_FORMATTYPE colorFormat,
- const sp<ISurface> &surface,
+ const sp<ISurface> &isurface,
+ const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
size_t decodedWidth, size_t decodedHeight);
@@ -147,7 +149,8 @@
bool previewOnly,
const char *componentName,
OMX_COLOR_FORMATTYPE colorFormat,
- const sp<ISurface> &surface,
+ const sp<ISurface> &isurface,
+ const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
size_t decodedWidth, size_t decodedHeight) {
if (!previewOnly) {
@@ -173,7 +176,7 @@
if (func) {
mTarget =
- (*func)(surface, componentName, colorFormat,
+ (*func)(isurface, componentName, colorFormat,
displayWidth, displayHeight,
decodedWidth, decodedHeight);
}
@@ -619,8 +622,18 @@
return OK;
}
+void AwesomePlayer::notifyVideoSize_l() {
+ sp<MetaData> meta = mVideoSource->getFormat();
+
+ int32_t decodedWidth, decodedHeight;
+ CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
+ CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
+
+ notifyListener_l(MEDIA_SET_VIDEO_SIZE, decodedWidth, decodedHeight);
+}
+
void AwesomePlayer::initRenderer_l() {
- if (mISurface != NULL) {
+ if (mSurface != NULL || mISurface != NULL) {
sp<MetaData> meta = mVideoSource->getFormat();
int32_t format;
@@ -637,7 +650,18 @@
// before creating a new one.
IPCThreadState::self()->flushCommands();
- if (!strncmp("OMX.", component, 4)) {
+ if (mSurface != NULL) {
+ // Other decoders are instantiated locally and as a consequence
+ // allocate their buffers in local address space.
+ mVideoRenderer = new AwesomeLocalRenderer(
+ false, // previewOnly
+ component,
+ (OMX_COLOR_FORMATTYPE)format,
+ mISurface,
+ mSurface,
+ mVideoWidth, mVideoHeight,
+ decodedWidth, decodedHeight);
+ } else {
// Our OMX codecs allocate buffers on the media_server side
// therefore they require a remote IOMXRenderer that knows how
// to display them.
@@ -647,16 +671,6 @@
(OMX_COLOR_FORMATTYPE)format,
decodedWidth, decodedHeight,
mVideoWidth, mVideoHeight));
- } else {
- // Other decoders are instantiated locally and as a consequence
- // allocate their buffers in local address space.
- mVideoRenderer = new AwesomeLocalRenderer(
- false, // previewOnly
- component,
- (OMX_COLOR_FORMATTYPE)format,
- mISurface,
- mVideoWidth, mVideoHeight,
- decodedWidth, decodedHeight);
}
}
}
@@ -695,6 +709,12 @@
mISurface = isurface;
}
+void AwesomePlayer::setSurface(const sp<Surface> &surface) {
+ Mutex::Autolock autoLock(mLock);
+
+ mSurface = surface;
+}
+
void AwesomePlayer::setAudioSink(
const sp<MediaPlayerBase::AudioSink> &audioSink) {
Mutex::Autolock autoLock(mLock);
@@ -937,6 +957,8 @@
if (err == INFO_FORMAT_CHANGED) {
LOGV("VideoSource signalled format change.");
+ notifyVideoSize_l();
+
if (mVideoRenderer != NULL) {
mVideoRendererIsPreview = false;
initRenderer_l();
@@ -1422,10 +1444,10 @@
Mutex::Autolock autoLock(mLock);
if (mIsAsyncPrepare) {
- if (mVideoWidth < 0 || mVideoHeight < 0) {
+ if (mVideoSource == NULL) {
notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
} else {
- notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
+ notifyVideoSize_l();
}
notifyListener_l(MEDIA_PREPARED);
@@ -1540,13 +1562,14 @@
mFlags = state->mFlags & (LOOPING | AT_EOS);
- if (state->mLastVideoFrame && mISurface != NULL) {
+ if (state->mLastVideoFrame && (mSurface != NULL || mISurface != NULL)) {
mVideoRenderer =
new AwesomeLocalRenderer(
true, // previewOnly
"",
(OMX_COLOR_FORMATTYPE)state->mColorFormat,
mISurface,
+ mSurface,
state->mVideoWidth,
state->mVideoHeight,
state->mDecodedWidth,
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 6bb54bd..e36d9fe 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -60,6 +60,7 @@
bool isAudio() const { return mIsAudio; }
bool isMPEG4() const { return mIsMPEG4; }
void addChunkOffset(off_t offset) { mChunkOffsets.push_back(offset); }
+ status_t dump(int fd, const Vector<String16>& args) const;
private:
MPEG4Writer *mOwner;
@@ -174,6 +175,9 @@
// value, the user-supplied time scale will be used.
void setTimeScale();
+ // Simple validation on the codec specific data
+ status_t checkCodecSpecificData() const;
+
Track(const Track &);
Track &operator=(const Track &);
};
@@ -214,6 +218,37 @@
mTracks.clear();
}
+status_t MPEG4Writer::dump(
+ int fd, const Vector<String16>& args) {
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, SIZE, " MPEG4Writer %p\n", this);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false");
+ result.append(buffer);
+ ::write(fd, result.string(), result.size());
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it) {
+ (*it)->dump(fd, args);
+ }
+ return OK;
+}
+
+status_t MPEG4Writer::Track::dump(
+ int fd, const Vector<String16>& args) const {
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video");
+ result.append(buffer);
+ snprintf(buffer, SIZE, " reached EOS: %s\n",
+ mReachedEOS? "true": "false");
+ result.append(buffer);
+ ::write(fd, result.string(), result.size());
+ return OK;
+}
+
status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
Track *track = new Track(this, source);
mTracks.push_back(track);
@@ -1521,10 +1556,24 @@
CHECK(timestampUs >= 0);
if (mNumSamples > 1) {
if (timestampUs <= lastTimestampUs) {
- LOGW("Drop a frame, since it arrives too late!");
+ LOGW("Frame arrives too late!");
+#if 0
+ // Drop the late frame.
copy->release();
copy = NULL;
continue;
+#else
+ // Don't drop the late frame, since dropping a frame may cause
+ // problems later during playback
+
+ // The idea here is to avoid having two or more samples with the
+ // same timestamp in the output file.
+ if (mTimeScale >= 1000000LL) {
+ timestampUs += 1;
+ } else {
+ timestampUs += (1000000LL + (mTimeScale >> 1)) / mTimeScale;
+ }
+#endif
}
}
@@ -1624,6 +1673,8 @@
if (mSampleSizes.empty()) {
err = ERROR_MALFORMED;
+ } else if (OK != checkCodecSpecificData()) {
+ err = ERROR_MALFORMED;
}
mOwner->trackProgressStatus(this, -1, err);
@@ -1833,6 +1884,27 @@
return mEstimatedTrackSizeBytes;
}
+status_t MPEG4Writer::Track::checkCodecSpecificData() const {
+ const char *mime;
+ CHECK(mMeta->findCString(kKeyMIMEType, &mime));
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
+ !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
+ !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
+ if (!mCodecSpecificData ||
+ mCodecSpecificDataSize <= 0) {
+ // Missing codec specific data
+ return ERROR_MALFORMED;
+ }
+ } else {
+ if (mCodecSpecificData ||
+ mCodecSpecificDataSize > 0) {
+ // Unexepected codec specific data found
+ return ERROR_MALFORMED;
+ }
+ }
+ return OK;
+}
+
void MPEG4Writer::Track::writeTrackHeader(
int32_t trackID, bool use32BitOffset) {
const char *mime;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 4741b1d..b39157e 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -146,29 +146,36 @@
static const CodecInfo kDecoderInfo[] = {
{ MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
+ { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.Nvidia.mp3.decoder" },
// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
{ MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" },
// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.PV.mp3dec" },
// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
+ { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amr.decoder" },
{ MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" },
// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.PV.amrdec" },
+ { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amrwb.decoder" },
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBDecoder" },
// { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.PV.amrdec" },
+ { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.Nvidia.aac.decoder" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "AACDecoder" },
// { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacdec" },
{ MEDIA_MIMETYPE_AUDIO_G711_ALAW, "G711Decoder" },
{ MEDIA_MIMETYPE_AUDIO_G711_MLAW, "G711Decoder" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.decode" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
// { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4dec" },
+ { MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.decode" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
// { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263dec" },
+ { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.decode" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.Decoder" },
@@ -199,6 +206,7 @@
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.encoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
+ { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.encoder" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "AVCEncoder" },
// { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" },
};
@@ -337,6 +345,13 @@
uint32_t OMXCodec::getComponentQuirks(const char *componentName) {
uint32_t quirks = 0;
+ if (!strcmp(componentName, "OMX.Nvidia.amr.decoder") ||
+ !strcmp(componentName, "OMX.Nvidia.amrwb.decoder") ||
+ !strcmp(componentName, "OMX.Nvidia.aac.decoder") ||
+ !strcmp(componentName, "OMX.Nvidia.mp3.decoder")) {
+ quirks |= kDecoderLiesAboutNumberOfChannels;
+ }
+
if (!strcmp(componentName, "OMX.PV.avcdec")) {
quirks |= kWantsNALFragments;
}
@@ -854,6 +869,10 @@
OMX_COLOR_FORMATTYPE colorFormat;
CHECK_EQ(OK, findTargetColorFormat(meta, &colorFormat));
+ if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName)) {
+ colorFormat = OMX_COLOR_FormatYUV420Planar;
+ }
+
status_t err;
OMX_PARAM_PORTDEFINITIONTYPE def;
OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
@@ -1193,6 +1212,10 @@
h264type.bMBAFF = OMX_FALSE;
h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
+ if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName)) {
+ h264type.eLevel = OMX_VIDEO_AVCLevelMax;
+ }
+
err = mOMX->setParameter(
mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
CHECK_EQ(err, OK);
diff --git a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
index 389180c..52a391f 100644
--- a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
@@ -338,10 +338,15 @@
MediaBuffer *outputBuffer;
CHECK_EQ(OK, mGroup->acquire_buffer(&outputBuffer));
+ uint8_t *outPtr = (uint8_t *) outputBuffer->data();
+ uint32_t dataLength = outputBuffer->size();
- // Add 4 bytes for the start code 0x00000001
- uint8_t *outPtr = (uint8_t *) outputBuffer->data() + 4;
- uint32_t dataLength = outputBuffer->size() - 4;
+ if (!mSpsPpsHeaderReceived && mNumInputFrames < 0) {
+ // 4 bytes are reserved for holding the start code 0x00000001
+ // of the sequence parameter set at the beginning.
+ outPtr += 4;
+ dataLength -= 4;
+ }
int32_t type;
AVCEnc_Status encoderStatus = AVCENC_SUCCESS;
@@ -358,7 +363,7 @@
switch (type) {
case AVC_NALTYPE_SPS:
++mNumInputFrames;
- memcpy(outputBuffer->data(), "\x00\x00\x00\x01", 4);
+ memcpy((uint8_t *)outputBuffer->data(), "\x00\x00\x00\x01", 4);
outputBuffer->set_range(0, dataLength + 4);
outPtr += (dataLength + 4); // 4 bytes for next start code
dataLength = outputBuffer->size() -
diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk
index b9ba1be..2b63235 100644
--- a/media/libstagefright/colorconversion/Android.mk
+++ b/media/libstagefright/colorconversion/Android.mk
@@ -6,7 +6,8 @@
SoftwareRenderer.cpp
LOCAL_C_INCLUDES := \
- $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+ $(TOP)/hardware/msm7k
LOCAL_SHARED_LIBRARIES := \
libbinder \
@@ -17,6 +18,11 @@
libsurfaceflinger_client\
libcamera_client
+# ifeq ($(TARGET_BOARD_PLATFORM),msm7k)
+ifeq ($(TARGET_PRODUCT),passion)
+ LOCAL_CFLAGS += -DHAS_YCBCR420_SP_ADRENO
+endif
+
LOCAL_MODULE:= libstagefright_color_conversion
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index a6dbf69..507fa5a 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -22,65 +22,172 @@
#include <binder/MemoryHeapBase.h>
#include <binder/MemoryHeapPmem.h>
#include <media/stagefright/MediaDebug.h>
-#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/Surface.h>
+#include <ui/android_native_buffer.h>
+#include <ui/GraphicBufferMapper.h>
+
+// XXX: Temporary hack to allow referencing the _ADRENO pixel format here.
+#include <libgralloc-qsd8k/gralloc_priv.h>
namespace android {
SoftwareRenderer::SoftwareRenderer(
OMX_COLOR_FORMATTYPE colorFormat,
- const sp<ISurface> &surface,
+ const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
size_t decodedWidth, size_t decodedHeight)
: mColorFormat(colorFormat),
- mConverter(colorFormat, OMX_COLOR_Format16bitRGB565),
- mISurface(surface),
+ mConverter(NULL),
+ mYUVMode(None),
+ mSurface(surface),
mDisplayWidth(displayWidth),
mDisplayHeight(displayHeight),
mDecodedWidth(decodedWidth),
- mDecodedHeight(decodedHeight),
- mFrameSize(mDecodedWidth * mDecodedHeight * 2), // RGB565
- mIndex(0) {
- mMemoryHeap = new MemoryHeapBase("/dev/pmem_adsp", 2 * mFrameSize);
- if (mMemoryHeap->heapID() < 0) {
- LOGI("Creating physical memory heap failed, reverting to regular heap.");
- mMemoryHeap = new MemoryHeapBase(2 * mFrameSize);
- } else {
- sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(mMemoryHeap);
- pmemHeap->slap();
- mMemoryHeap = pmemHeap;
+ mDecodedHeight(decodedHeight) {
+ LOGI("input format = %d", mColorFormat);
+ LOGI("display = %d x %d, decoded = %d x %d",
+ mDisplayWidth, mDisplayHeight, mDecodedWidth, mDecodedHeight);
+
+ int halFormat;
+ switch (mColorFormat) {
+#if HAS_YCBCR420_SP_ADRENO
+ case OMX_COLOR_FormatYUV420Planar:
+ {
+ halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO;
+ mYUVMode = YUV420ToYUV420sp;
+ break;
+ }
+
+ case 0x7fa30c00:
+ {
+ halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO;
+ mYUVMode = YUV420spToYUV420sp;
+ break;
+ }
+#endif
+
+ default:
+ halFormat = HAL_PIXEL_FORMAT_RGB_565;
+
+ mConverter = new ColorConverter(
+ mColorFormat, OMX_COLOR_Format16bitRGB565);
+ CHECK(mConverter->isValid());
+ break;
}
- CHECK(mISurface.get() != NULL);
+ CHECK(mSurface.get() != NULL);
CHECK(mDecodedWidth > 0);
CHECK(mDecodedHeight > 0);
- CHECK(mMemoryHeap->heapID() >= 0);
- CHECK(mConverter.isValid());
+ CHECK(mConverter == NULL || mConverter->isValid());
- ISurface::BufferHeap bufferHeap(
- mDisplayWidth, mDisplayHeight,
- mDecodedWidth, mDecodedHeight,
- PIXEL_FORMAT_RGB_565,
- mMemoryHeap);
+ CHECK_EQ(0,
+ native_window_set_usage(
+ mSurface.get(),
+ GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
+ | GRALLOC_USAGE_HW_TEXTURE));
- status_t err = mISurface->registerBuffers(bufferHeap);
- CHECK_EQ(err, OK);
+ CHECK_EQ(0, native_window_set_buffer_count(mSurface.get(), 2));
+
+ // Width must be multiple of 32???
+ CHECK_EQ(0, native_window_set_buffers_geometry(
+ mSurface.get(), mDecodedWidth, mDecodedHeight,
+ halFormat));
}
SoftwareRenderer::~SoftwareRenderer() {
- mISurface->unregisterBuffers();
+ delete mConverter;
+ mConverter = NULL;
+}
+
+static inline size_t ALIGN(size_t x, size_t alignment) {
+ return (x + alignment - 1) & ~(alignment - 1);
}
void SoftwareRenderer::render(
const void *data, size_t size, void *platformPrivate) {
- size_t offset = mIndex * mFrameSize;
- void *dst = (uint8_t *)mMemoryHeap->getBase() + offset;
+ android_native_buffer_t *buf;
+ CHECK_EQ(0, mSurface->dequeueBuffer(mSurface.get(), &buf));
+ CHECK_EQ(0, mSurface->lockBuffer(mSurface.get(), buf));
- mConverter.convert(
- mDecodedWidth, mDecodedHeight,
- data, 0, dst, 2 * mDecodedWidth);
+ GraphicBufferMapper &mapper = GraphicBufferMapper::get();
- mISurface->postBuffer(offset);
- mIndex = 1 - mIndex;
+ Rect bounds(mDecodedWidth, mDecodedHeight);
+
+ void *dst;
+ CHECK_EQ(0, mapper.lock(
+ buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst));
+
+ if (mConverter) {
+ mConverter->convert(
+ mDecodedWidth, mDecodedHeight,
+ data, 0, dst, buf->stride * 2);
+ } else if (mYUVMode == YUV420spToYUV420sp) {
+ // Input and output are both YUV420sp, but the alignment requirements
+ // are different.
+ size_t srcYStride = mDecodedWidth;
+ const uint8_t *srcY = (const uint8_t *)data;
+ uint8_t *dstY = (uint8_t *)dst;
+ for (size_t i = 0; i < mDecodedHeight; ++i) {
+ memcpy(dstY, srcY, mDecodedWidth);
+ srcY += srcYStride;
+ dstY += buf->stride;
+ }
+
+ size_t srcUVStride = (mDecodedWidth + 1) & ~1;
+ size_t dstUVStride = ALIGN(mDecodedWidth / 2, 32) * 2;
+
+ const uint8_t *srcUV = (const uint8_t *)data
+ + mDecodedHeight * mDecodedWidth;
+
+ size_t dstUVOffset = ALIGN(ALIGN(mDecodedHeight, 32) * buf->stride, 4096);
+ uint8_t *dstUV = (uint8_t *)dst + dstUVOffset;
+
+ for (size_t i = 0; i < (mDecodedHeight + 1) / 2; ++i) {
+ memcpy(dstUV, srcUV, (mDecodedWidth + 1) & ~1);
+ srcUV += srcUVStride;
+ dstUV += dstUVStride;
+ }
+ } else if (mYUVMode == YUV420ToYUV420sp) {
+ // Input is YUV420 planar, output is YUV420sp, adhere to proper
+ // alignment requirements.
+ size_t srcYStride = mDecodedWidth;
+ const uint8_t *srcY = (const uint8_t *)data;
+ uint8_t *dstY = (uint8_t *)dst;
+ for (size_t i = 0; i < mDecodedHeight; ++i) {
+ memcpy(dstY, srcY, mDecodedWidth);
+ srcY += srcYStride;
+ dstY += buf->stride;
+ }
+
+ size_t srcUVStride = (mDecodedWidth + 1) / 2;
+ size_t dstUVStride = ALIGN(mDecodedWidth / 2, 32) * 2;
+
+ const uint8_t *srcU = (const uint8_t *)data
+ + mDecodedHeight * mDecodedWidth;
+
+ const uint8_t *srcV =
+ srcU + ((mDecodedWidth + 1) / 2) * ((mDecodedHeight + 1) / 2);
+
+ size_t dstUVOffset = ALIGN(ALIGN(mDecodedHeight, 32) * buf->stride, 4096);
+ uint8_t *dstUV = (uint8_t *)dst + dstUVOffset;
+
+ for (size_t i = 0; i < (mDecodedHeight + 1) / 2; ++i) {
+ for (size_t j = 0; j < (mDecodedWidth + 1) / 2; ++j) {
+ dstUV[2 * j + 1] = srcU[j];
+ dstUV[2 * j] = srcV[j];
+ }
+ srcU += srcUVStride;
+ srcV += srcUVStride;
+ dstUV += dstUVStride;
+ }
+ } else {
+ memcpy(dst, data, size);
+ }
+
+ CHECK_EQ(0, mapper.unlock(buf->handle));
+
+ CHECK_EQ(0, mSurface->queueBuffer(mSurface.get(), buf));
+ buf = NULL;
}
} // namespace android
diff --git a/media/libstagefright/include/ARTSPController.h b/media/libstagefright/include/ARTSPController.h
index 55efd41..2542e4e 100644
--- a/media/libstagefright/include/ARTSPController.h
+++ b/media/libstagefright/include/ARTSPController.h
@@ -19,6 +19,7 @@
#define A_RTSP_CONTROLLER_H_
#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AHandlerReflector.h>
#include <media/stagefright/MediaExtractor.h>
namespace android {
@@ -38,12 +39,32 @@
virtual sp<MetaData> getTrackMetaData(
size_t index, uint32_t flags);
+ void onMessageReceived(const sp<AMessage> &msg);
+
protected:
virtual ~ARTSPController();
private:
+ enum {
+ kWhatConnectDone = 'cdon',
+ kWhatDisconnectDone = 'ddon',
+ };
+
+ enum State {
+ DISCONNECTED,
+ CONNECTED,
+ CONNECTING,
+ };
+
+ Mutex mLock;
+ Condition mCondition;
+
+ State mState;
+ status_t mConnectionResult;
+
sp<ALooper> mLooper;
sp<MyHandler> mHandler;
+ sp<AHandlerReflector<ARTSPController> > mReflector;
DISALLOW_EVIL_CONSTRUCTORS(ARTSPController);
};
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 55e2c36..f34eb45 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -76,6 +76,7 @@
bool isPlaying() const;
void setISurface(const sp<ISurface> &isurface);
+ void setSurface(const sp<Surface> &surface);
void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink);
status_t setLooping(bool shouldLoop);
@@ -117,6 +118,7 @@
wp<MediaPlayerBase> mListener;
sp<ISurface> mISurface;
+ sp<Surface> mSurface;
sp<MediaPlayerBase::AudioSink> mAudioSink;
SystemTimeSource mSystemTimeSource;
@@ -219,6 +221,7 @@
status_t seekTo_l(int64_t timeUs);
status_t pause_l();
void initRenderer_l();
+ void notifyVideoSize_l();
void seekAudioIfNecessary_l();
void cancelPlayerEvents(bool keepBufferingGoing = false);
diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h
index 9eed089..8d58056 100644
--- a/media/libstagefright/include/SoftwareRenderer.h
+++ b/media/libstagefright/include/SoftwareRenderer.h
@@ -24,14 +24,14 @@
namespace android {
-class ISurface;
+class Surface;
class MemoryHeapBase;
class SoftwareRenderer : public VideoRenderer {
public:
SoftwareRenderer(
OMX_COLOR_FORMATTYPE colorFormat,
- const sp<ISurface> &surface,
+ const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
size_t decodedWidth, size_t decodedHeight);
@@ -41,14 +41,18 @@
const void *data, size_t size, void *platformPrivate);
private:
+ enum YUVMode {
+ None,
+ YUV420ToYUV420sp,
+ YUV420spToYUV420sp,
+ };
+
OMX_COLOR_FORMATTYPE mColorFormat;
- ColorConverter mConverter;
- sp<ISurface> mISurface;
+ ColorConverter *mConverter;
+ YUVMode mYUVMode;
+ sp<Surface> mSurface;
size_t mDisplayWidth, mDisplayHeight;
size_t mDecodedWidth, mDecodedHeight;
- size_t mFrameSize;
- sp<MemoryHeapBase> mMemoryHeap;
- int mIndex;
SoftwareRenderer(const SoftwareRenderer &);
SoftwareRenderer &operator=(const SoftwareRenderer &);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 6de761f..88b9605 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -495,12 +495,17 @@
}
if (!impl) {
+#if 0
LOGW("Using software renderer.");
impl = new SoftwareRenderer(
colorFormat,
surface,
displayWidth, displayHeight,
encodedWidth, encodedHeight);
+#else
+ CHECK(!"Should not be here.");
+ return NULL;
+#endif
}
return new OMXRenderer(impl);
diff --git a/media/libstagefright/rtsp/ARTSPController.cpp b/media/libstagefright/rtsp/ARTSPController.cpp
index 195323e..ceae3a6 100644
--- a/media/libstagefright/rtsp/ARTSPController.cpp
+++ b/media/libstagefright/rtsp/ARTSPController.cpp
@@ -26,31 +26,57 @@
namespace android {
ARTSPController::ARTSPController(const sp<ALooper> &looper)
- : mLooper(looper) {
+ : mState(DISCONNECTED),
+ mLooper(looper) {
+ mReflector = new AHandlerReflector<ARTSPController>(this);
+ looper->registerHandler(mReflector);
}
ARTSPController::~ARTSPController() {
+ disconnect();
+ mLooper->unregisterHandler(mReflector->id());
}
status_t ARTSPController::connect(const char *url) {
- if (mHandler != NULL) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mState != DISCONNECTED) {
return ERROR_ALREADY_CONNECTED;
}
+ sp<AMessage> msg = new AMessage(kWhatConnectDone, mReflector->id());
+
mHandler = new MyHandler(url, mLooper);
- mHandler->connect();
- sleep(10);
+ mState = CONNECTING;
- return OK;
+ mHandler->connect(msg);
+
+ while (mState == CONNECTING) {
+ mCondition.wait(mLock);
+ }
+
+ if (mState != CONNECTED) {
+ mHandler.clear();
+ }
+
+ return mConnectionResult;
}
void ARTSPController::disconnect() {
- if (mHandler == NULL) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mState != CONNECTED) {
return;
}
- mHandler->disconnect();
+ sp<AMessage> msg = new AMessage(kWhatDisconnectDone, mReflector->id());
+ mHandler->disconnect(msg);
+
+ while (mState == CONNECTED) {
+ mCondition.wait(mLock);
+ }
+
mHandler.clear();
}
@@ -75,4 +101,31 @@
return mHandler->getPacketSource(index)->getFormat();
}
+void ARTSPController::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatConnectDone:
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ CHECK(msg->findInt32("result", &mConnectionResult));
+ mState = (mConnectionResult == OK) ? CONNECTED : DISCONNECTED;
+
+ mCondition.signal();
+ break;
+ }
+
+ case kWhatDisconnectDone:
+ {
+ Mutex::Autolock autoLock(mLock);
+ mState = DISCONNECTED;
+ mCondition.signal();
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
} // namespace android
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 3e75ffe..b2419bf 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -45,18 +45,21 @@
PRIORITY_HIGHEST);
}
- void connect() {
+ void connect(const sp<AMessage> &doneMsg) {
+ mDoneMsg = doneMsg;
+
mLooper->registerHandler(this);
mLooper->registerHandler(mConn);
(1 ? mNetLooper : mLooper)->registerHandler(mRTPConn);
- sp<AMessage> reply = new AMessage('conn', id());
+ sp<AMessage> reply = new AMessage('conn', id());
mConn->connect(mSessionURL.c_str(), reply);
}
- void disconnect() {
- sp<AMessage> reply = new AMessage('disc', id());
- mConn->disconnect(reply);
+ void disconnect(const sp<AMessage> &doneMsg) {
+ mDoneMsg = doneMsg;
+
+ (new AMessage('abor', id()))->post();
}
virtual void onMessageReceived(const sp<AMessage> &msg) {
@@ -250,8 +253,9 @@
CHECK_EQ(response->mStatusCode, 200u);
- sp<AMessage> msg = new AMessage('abor', id());
- msg->post(60000000ll);
+ mDoneMsg->setInt32("result", OK);
+ mDoneMsg->post();
+ mDoneMsg = NULL;
} else {
sp<AMessage> reply = new AMessage('disc', id());
mConn->disconnect(reply);
@@ -301,6 +305,11 @@
case 'quit':
{
+ if (mDoneMsg != NULL) {
+ mDoneMsg->setInt32("result", UNKNOWN_ERROR);
+ mDoneMsg->post();
+ mDoneMsg = NULL;
+ }
break;
}
@@ -380,6 +389,8 @@
};
Vector<TrackInfo> mTracks;
+ sp<AMessage> mDoneMsg;
+
void setupTrack(size_t index) {
sp<APacketSource> source =
new APacketSource(mSessionDesc, index);
diff --git a/media/tests/players/invoke_mock_media_player.cpp b/media/tests/players/invoke_mock_media_player.cpp
index b3cc8b6..53308be 100644
--- a/media/tests/players/invoke_mock_media_player.cpp
+++ b/media/tests/players/invoke_mock_media_player.cpp
@@ -26,6 +26,7 @@
using android::INVALID_OPERATION;
using android::ISurface;
+using android::Surface;
using android::MediaPlayerBase;
using android::OK;
using android::Parcel;
@@ -67,7 +68,8 @@
}
virtual status_t setDataSource(int fd, int64_t offset, int64_t length) {return OK;}
- virtual status_t setVideoSurface(const sp<ISurface>& surface) {return OK;}
+ virtual status_t setVideoISurface(const sp<ISurface>& surface) {return OK;}
+ virtual status_t setVideoSurface(const sp<Surface>& surface) {return OK;}
virtual status_t prepare() {return OK;}
virtual status_t prepareAsync() {return OK;}
virtual status_t start() {return OK;}
diff --git a/native/android/Android.mk b/native/android/Android.mk
index bd2b27a..cc35a3a 100644
--- a/native/android/Android.mk
+++ b/native/android/Android.mk
@@ -12,7 +12,8 @@
looper.cpp \
native_activity.cpp \
native_window.cpp \
- sensor.cpp
+ sensor.cpp \
+ storage_manager.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
@@ -23,6 +24,9 @@
libsurfaceflinger_client \
libandroid_runtime
+LOCAL_STATIC_LIBRARIES := \
+ libstorage
+
LOCAL_C_INCLUDES += \
frameworks/base/native/include \
frameworks/base/core/jni/android \
diff --git a/native/android/storage_manager.cpp b/native/android/storage_manager.cpp
new file mode 100644
index 0000000..6dbe746
--- /dev/null
+++ b/native/android/storage_manager.cpp
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "NStorage"
+
+#include <android/storage_manager.h>
+#include <storage/IMountService.h>
+
+#include <binder/Binder.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+
+using namespace android;
+
+struct ObbActionListener : public BnObbActionListener {
+private:
+ sp<AStorageManager> mStorageManager;
+
+public:
+ ObbActionListener(AStorageManager* mgr) :
+ mStorageManager(mgr)
+ {}
+
+ virtual void onObbResult(const android::String16& filename, const android::String16& state) {
+ LOGD("Got obb result (%s, %s)\n", String8(filename).string(), String8(state).string());
+ }
+};
+
+struct AStorageManager : public RefBase {
+protected:
+ void* mObbCallback;
+ sp<ObbActionListener> mObbActionListener;
+ sp<IMountService> mMountService;
+
+public:
+ AStorageManager() :
+ mObbCallback(NULL)
+ {
+ }
+
+ bool initialize() {
+ sp<IServiceManager> sm = defaultServiceManager();
+ if (sm == NULL) {
+ LOGE("Couldn't get default ServiceManager\n");
+ return false;
+ }
+
+ mMountService = interface_cast<IMountService>(sm->getService(String16("mount")));
+ if (mMountService == NULL) {
+ LOGE("Couldn't get connection to MountService\n");
+ return false;
+ }
+
+ mObbActionListener = new ObbActionListener(this);
+
+ return true;
+ }
+
+ void setObbCallback(void* cb) {
+ mObbCallback = cb;
+ }
+
+ void mountObb(const char* filename, const char* key) {
+ String16 filename16(filename);
+ String16 key16(key);
+ mMountService->mountObb(filename16, key16, mObbActionListener);
+ }
+
+ void unmountObb(const char* filename, const bool force) {
+ String16 filename16(filename);
+ mMountService->unmountObb(filename16, force);
+ }
+
+ int isObbMounted(const char* filename) {
+ String16 filename16(filename);
+ return mMountService->isObbMounted(filename16);
+ }
+
+ const char* getMountedObbPath(const char* filename) {
+ String16 filename16(filename);
+ String16 path16;
+ if (mMountService->getMountedObbPath(filename16, path16)) {
+ return String8(path16).string();
+ } else {
+ return NULL;
+ }
+ }
+};
+
+
+AStorageManager* AStorageManager_new() {
+ sp<AStorageManager> mgr = new AStorageManager();
+ if (mgr == NULL || !mgr->initialize()) {
+ return NULL;
+ }
+ mgr->incStrong((void*)AStorageManager_new);
+ return static_cast<AStorageManager*>(mgr.get());
+}
+
+void AStorageManager_delete(AStorageManager* mgr) {
+ if (mgr) {
+ mgr->decStrong((void*)AStorageManager_new);
+ }
+}
+
+void AStorageManager_setObbCallback(AStorageManager* mgr, void* cb) {
+ mgr->setObbCallback(cb);
+}
+
+void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key) {
+ mgr->mountObb(filename, key);
+}
+
+void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force) {
+ mgr->unmountObb(filename, force != 0);
+}
+
+int AStorageManager_isObbMounted(AStorageManager* mgr, const char* filename) {
+ return mgr->isObbMounted(filename) != 0;
+}
+
+const char* AStorageManager_getMountedObbPath(AStorageManager* mgr, const char* filename) {
+ return mgr->getMountedObbPath(filename);
+}
diff --git a/native/include/android/storage_manager.h b/native/include/android/storage_manager.h
new file mode 100644
index 0000000..bbed8a4
--- /dev/null
+++ b/native/include/android/storage_manager.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+
+#ifndef ANDROID_STORAGE_MANAGER_H
+#define ANDROID_STORAGE_MANAGER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct AStorageManager;
+typedef struct AStorageManager AStorageManager;
+
+
+/**
+ * Obtains a new instance of AStorageManager.
+ */
+AStorageManager* AStorageManager_new();
+
+/**
+ * Release AStorageManager instance.
+ */
+void AStorageManager_delete(AStorageManager* mgr);
+
+/**
+ * Callback to call when requested OBB is complete.
+ */
+void AStorageManager_setObbCallback(AStorageManager* mgr, void* cb);
+
+/**
+ * Attempts to mount an OBB file.
+ */
+void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key);
+
+/**
+ * Attempts to unmount an OBB file.
+ */
+void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force);
+
+/**
+ * Check whether an OBB is mounted.
+ */
+int AStorageManager_isObbMounted(AStorageManager* mgr, const char* filename);
+
+/**
+ * Get the mounted path for an OBB.
+ */
+const char* AStorageManager_getMountedObbPath(AStorageManager* mgr, const char* filename);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_PACKAGE_MANAGER_H
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_0.png b/packages/SystemUI/res/drawable-mdpi/battery_0.png
index b5d36cc..77162c8 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_100.png b/packages/SystemUI/res/drawable-mdpi/battery_100.png
index 75cc409..588a74b 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_20.png b/packages/SystemUI/res/drawable-mdpi/battery_20.png
deleted file mode 100644
index c0d0030..0000000
--- a/packages/SystemUI/res/drawable-mdpi/battery_20.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_25.png b/packages/SystemUI/res/drawable-mdpi/battery_25.png
new file mode 100644
index 0000000..b11570b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/battery_25.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_40.png b/packages/SystemUI/res/drawable-mdpi/battery_40.png
deleted file mode 100644
index e301c08..0000000
--- a/packages/SystemUI/res/drawable-mdpi/battery_40.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_50.png b/packages/SystemUI/res/drawable-mdpi/battery_50.png
new file mode 100644
index 0000000..94d7eca
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/battery_50.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_60.png b/packages/SystemUI/res/drawable-mdpi/battery_60.png
deleted file mode 100644
index 0fde1fa..0000000
--- a/packages/SystemUI/res/drawable-mdpi/battery_60.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_75.png b/packages/SystemUI/res/drawable-mdpi/battery_75.png
new file mode 100644
index 0000000..3cb3591
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/battery_75.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_80.png b/packages/SystemUI/res/drawable-mdpi/battery_80.png
deleted file mode 100644
index 15c4e1c..0000000
--- a/packages/SystemUI/res/drawable-mdpi/battery_80.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 6533677..cf436ad 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 e8976a2..0011a1b 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_20.png b/packages/SystemUI/res/drawable-mdpi/signal_20.png
deleted file mode 100644
index 651e2a9..0000000
--- a/packages/SystemUI/res/drawable-mdpi/signal_20.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_25.png b/packages/SystemUI/res/drawable-mdpi/signal_25.png
new file mode 100644
index 0000000..69c643f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/signal_25.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_40.png b/packages/SystemUI/res/drawable-mdpi/signal_40.png
deleted file mode 100644
index 6ba7906..0000000
--- a/packages/SystemUI/res/drawable-mdpi/signal_40.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_50.png b/packages/SystemUI/res/drawable-mdpi/signal_50.png
new file mode 100644
index 0000000..c8acd72
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/signal_50.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_60.png b/packages/SystemUI/res/drawable-mdpi/signal_60.png
deleted file mode 100644
index 6d2e812..0000000
--- a/packages/SystemUI/res/drawable-mdpi/signal_60.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_75.png b/packages/SystemUI/res/drawable-mdpi/signal_75.png
new file mode 100644
index 0000000..9650dfa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/signal_75.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/signal_80.png b/packages/SystemUI/res/drawable-mdpi/signal_80.png
deleted file mode 100644
index a152623..0000000
--- a/packages/SystemUI/res/drawable-mdpi/signal_80.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_back_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_back_default.png
index dd64746..5c57802 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_back_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_back_default.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 66a3677..5c57802 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 4d19717..b2a94b6 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 830cbd5..b2a94b6 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_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_home_default.png
index b129210..f219ded 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_home_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_home_default.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 dcb2447..f219ded 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_icon_tray.9.png b/packages/SystemUI/res/drawable-mdpi/status_bar_icon_tray.9.png
index 07d00cb..502acce 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_icon_tray.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_icon_tray.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_recent_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_default.png
new file mode 100644
index 0000000..4dd8dc7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_default.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
new file mode 100644
index 0000000..4dd8dc7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/battery.xml b/packages/SystemUI/res/drawable/battery.xml
index c2294d1..f4a720d 100644
--- a/packages/SystemUI/res/drawable/battery.xml
+++ b/packages/SystemUI/res/drawable/battery.xml
@@ -23,13 +23,12 @@
<item android:maxLevel="5">
<animation-list android:oneshot="false">
<item android:drawable="@drawable/battery_0" android:duration="250" />
- <item android:drawable="@drawable/battery_20" android:duration="250" />
+ <item android:drawable="@drawable/battery_25" android:duration="250" />
</animation-list>
</item>
- <item android:maxLevel="20" android:drawable="@drawable/battery_20" />
- <item android:maxLevel="40" android:drawable="@drawable/battery_40" />
- <item android:maxLevel="60" android:drawable="@drawable/battery_60" />
- <item android:maxLevel="80" android:drawable="@drawable/battery_80" />
+ <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" />
<item android:maxLevel="101" android:drawable="@drawable/battery_100" />
</level-list>
diff --git a/packages/SystemUI/res/drawable/battery_charging.xml b/packages/SystemUI/res/drawable/battery_charging.xml
index 2fd0c6d..c9b77dd 100644
--- a/packages/SystemUI/res/drawable/battery_charging.xml
+++ b/packages/SystemUI/res/drawable/battery_charging.xml
@@ -19,33 +19,27 @@
-->
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:maxLevel="20">
+ <item android:maxLevel="25">
<animation-list android:oneshot="false">
<item android:drawable="@drawable/battery_0" android:duration="1000" />
- <item android:drawable="@drawable/battery_20" android:duration="1000" />
+ <item android:drawable="@drawable/battery_25" android:duration="1000" />
</animation-list>
</item>
- <item android:maxLevel="40">
+ <item android:maxLevel="50">
<animation-list android:oneshot="false">
- <item android:drawable="@drawable/battery_20" android:duration="1000" />
- <item android:drawable="@drawable/battery_40" android:duration="1000" />
+ <item android:drawable="@drawable/battery_25" android:duration="1000" />
+ <item android:drawable="@drawable/battery_50" android:duration="1000" />
</animation-list>
</item>
- <item android:maxLevel="60">
+ <item android:maxLevel="75">
<animation-list android:oneshot="false">
- <item android:drawable="@drawable/battery_40" android:duration="1000" />
- <item android:drawable="@drawable/battery_60" android:duration="1000" />
- </animation-list>
- </item>
- <item android:maxLevel="80">
- <animation-list android:oneshot="false">
- <item android:drawable="@drawable/battery_60" android:duration="1000" />
- <item android:drawable="@drawable/battery_80" android:duration="1000" />
+ <item android:drawable="@drawable/battery_50" android:duration="1000" />
+ <item android:drawable="@drawable/battery_75" android:duration="1000" />
</animation-list>
</item>
<item android:maxLevel="92">
<animation-list android:oneshot="false">
- <item android:drawable="@drawable/battery_80" android:duration="1000" />
+ <item android:drawable="@drawable/battery_75" android:duration="1000" />
<item android:drawable="@drawable/battery_100" android:duration="1000" />
</animation-list>
</item>
diff --git a/packages/SystemUI/res/drawable/signal.xml b/packages/SystemUI/res/drawable/signal.xml
index 8b4f56b..5aa211a 100644
--- a/packages/SystemUI/res/drawable/signal.xml
+++ b/packages/SystemUI/res/drawable/signal.xml
@@ -20,10 +20,9 @@
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:maxLevel="01" android:drawable="@drawable/signal_0" />
- <item android:maxLevel="20" android:drawable="@drawable/signal_20" />
- <item android:maxLevel="40" android:drawable="@drawable/signal_40" />
- <item android:maxLevel="60" android:drawable="@drawable/signal_60" />
- <item android:maxLevel="80" android:drawable="@drawable/signal_80" />
+ <item android:maxLevel="25" android:drawable="@drawable/signal_25" />
+ <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/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 2dabf72..ca9a484 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -199,6 +199,13 @@
/* Custom title feature is enabled and the user is trying to enable another feature */
throw new AndroidRuntimeException("You cannot combine custom titles with other title features");
}
+ if ((features & (1 << FEATURE_NO_TITLE)) != 0 && featureId == FEATURE_ACTION_BAR) {
+ return false; // Ignore. No title dominates.
+ }
+ if ((features & (1 << FEATURE_ACTION_BAR)) != 0 && featureId == FEATURE_NO_TITLE) {
+ // Remove the action bar feature if we have no title. No title dominates.
+ removeFeature(FEATURE_ACTION_BAR);
+ }
return super.requestFeature(featureId);
}
@@ -2365,11 +2372,15 @@
} else {
layoutResource = com.android.internal.R.layout.screen_title_icons;
}
+ // XXX Remove this once action bar supports these features.
+ removeFeature(FEATURE_ACTION_BAR);
// System.out.println("Title Icons!");
} else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0) {
// Special case for a window with only a progress bar (and title).
// XXX Need to have a no-title version of embedded windows.
layoutResource = com.android.internal.R.layout.screen_progress;
+ // XXX Remove this once action bar supports these features.
+ removeFeature(FEATURE_ACTION_BAR);
// System.out.println("Progress!");
} else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
// Special case for a window with a custom title.
@@ -2379,6 +2390,8 @@
} else {
layoutResource = com.android.internal.R.layout.screen_custom_title;
}
+ // XXX Remove this once action bar supports these features.
+ removeFeature(FEATURE_ACTION_BAR);
} else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
// If no other features and not embedded, only need a title.
// If the window is floating, we need a dialog layout
diff --git a/services/camera/libcameraservice/CameraHardwareStub.cpp b/services/camera/libcameraservice/CameraHardwareStub.cpp
index b3e0ee6..07b5a37 100644
--- a/services/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/services/camera/libcameraservice/CameraHardwareStub.cpp
@@ -101,9 +101,9 @@
mFakeCamera = 0; // paranoia
}
-sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
+status_t CameraHardwareStub::setPreviewWindow(const sp<ANativeWindow>& buf)
{
- return mPreviewHeap;
+ return NO_ERROR;
}
sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
diff --git a/services/camera/libcameraservice/CameraHardwareStub.h b/services/camera/libcameraservice/CameraHardwareStub.h
index d3427ba..9b66a76 100644
--- a/services/camera/libcameraservice/CameraHardwareStub.h
+++ b/services/camera/libcameraservice/CameraHardwareStub.h
@@ -29,7 +29,7 @@
class CameraHardwareStub : public CameraHardwareInterface {
public:
- virtual sp<IMemoryHeap> getPreviewHeap() const;
+ virtual status_t setPreviewWindow(const sp<ANativeWindow>& buf);
virtual sp<IMemoryHeap> getRawHeap() const;
virtual void setCallbacks(notify_callback notify_cb,
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 3b3904a..c6a9909 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -145,7 +145,12 @@
return NULL;
}
- client = new Client(this, cameraClient, cameraId, callingPid);
+ sp<CameraHardwareInterface> hardware = HAL_openCameraHardware(cameraId);
+ if (hardware == NULL) {
+ LOGE("Fail to open camera hardware (id=%d)", cameraId);
+ return NULL;
+ }
+ client = new Client(this, cameraClient, hardware, cameraId, callingPid);
mClient[cameraId] = client;
LOG1("CameraService::connect X");
return client;
@@ -285,16 +290,17 @@
// ----------------------------------------------------------------------------
CameraService::Client::Client(const sp<CameraService>& cameraService,
- const sp<ICameraClient>& cameraClient, int cameraId, int clientPid) {
+ const sp<ICameraClient>& cameraClient,
+ const sp<CameraHardwareInterface>& hardware,
+ int cameraId, int clientPid) {
int callingPid = getCallingPid();
LOG1("Client::Client E (pid %d)", callingPid);
mCameraService = cameraService;
mCameraClient = cameraClient;
+ mHardware = hardware;
mCameraId = cameraId;
mClientPid = clientPid;
-
- mHardware = HAL_openCameraHardware(cameraId);
mUseOverlay = mHardware->useOverlay();
mMsgEnabled = 0;
@@ -330,16 +336,9 @@
int callingPid = getCallingPid();
LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
- if (mSurface != 0 && !mUseOverlay) {
- pthread_t thr;
- // We unregister the buffers in a different thread because binder does
- // not let us make sychronous transactions in a binder destructor (that
- // is, upon our reaching a refcount of zero.)
- pthread_create(&thr,
- NULL, // attr
- unregister_surface,
- mSurface.get());
- pthread_join(thr, NULL);
+ // Clean up the ANativeWindow
+ if (mSurface != 0) {
+ setPreviewDisplay(0);
}
// set mClientPid to let disconnet() tear down the hardware
@@ -459,6 +458,11 @@
if (mUseOverlay) {
mOverlayRef = 0;
}
+ // Release the held ANativeWindow resources.
+ if (mPreviewWindow != 0) {
+ mPreviewWindow = 0;
+ mHardware->setPreviewWindow(mPreviewWindow);
+ }
mHardware.clear();
mCameraService->removeClient(mCameraClient);
@@ -469,8 +473,8 @@
// ----------------------------------------------------------------------------
-// set the ISurface that the preview will use
-status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) {
+// set the Surface that the preview will use
+status_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) {
LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
Mutex::Autolock lock(mLock);
status_t result = checkPidAndHardware();
@@ -480,7 +484,7 @@
// return if no change in surface.
// asBinder() is safe on NULL (returns NULL)
- if (surface->asBinder() == mSurface->asBinder()) {
+ if (getISurface(surface)->asBinder() == mSurface->asBinder()) {
return result;
}
@@ -490,44 +494,28 @@
// Force the destruction of any previous overlay
sp<Overlay> dummy;
mHardware->setOverlay(dummy);
- } else {
- mSurface->unregisterBuffers();
}
}
- mSurface = surface;
+ if (surface != 0) {
+ mSurface = getISurface(surface);
+ } else {
+ mSurface = 0;
+ }
+ mPreviewWindow = surface;
mOverlayRef = 0;
// If preview has been already started, set overlay or register preview
// buffers now.
if (mHardware->previewEnabled()) {
if (mUseOverlay) {
result = setOverlay();
- } else if (mSurface != 0) {
- result = registerPreviewBuffers();
+ } else if (mPreviewWindow != 0) {
+ result = mHardware->setPreviewWindow(mPreviewWindow);
}
}
return result;
}
-status_t CameraService::Client::registerPreviewBuffers() {
- int w, h;
- CameraParameters params(mHardware->getParameters());
- params.getPreviewSize(&w, &h);
-
- // FIXME: don't use a hardcoded format here.
- ISurface::BufferHeap buffers(w, h, w, h,
- HAL_PIXEL_FORMAT_YCrCb_420_SP,
- mOrientation,
- 0,
- mHardware->getPreviewHeap());
-
- status_t result = mSurface->registerBuffers(buffers);
- if (result != NO_ERROR) {
- LOGE("registerBuffers failed with status %d", result);
- }
- return result;
-}
-
status_t CameraService::Client::setOverlay() {
int w, h;
CameraParameters params(mHardware->getParameters());
@@ -618,14 +606,14 @@
switch(mode) {
case CAMERA_PREVIEW_MODE:
- if (mSurface == 0) {
+ if (mSurface == 0 && mPreviewWindow == 0) {
LOG1("mSurface is not set yet.");
// still able to start preview in this case.
}
return startPreviewMode();
case CAMERA_RECORDING_MODE:
- if (mSurface == 0) {
- LOGE("mSurface must be set before startRecordingMode.");
+ if (mSurface == 0 && mPreviewWindow == 0) {
+ LOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
return INVALID_OPERATION;
}
return startRecordingMode();
@@ -651,16 +639,10 @@
if (result != NO_ERROR) return result;
result = mHardware->startPreview();
} else {
+ // XXX: Set the orientation of the ANativeWindow.
+ mHardware->setPreviewWindow(mPreviewWindow);
enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
result = mHardware->startPreview();
- if (result != NO_ERROR) return result;
- // If preview display has been set, register preview buffers now.
- if (mSurface != 0) {
- // Unregister here because the surface may be previously registered
- // with the raw (snapshot) heap.
- mSurface->unregisterBuffers();
- result = registerPreviewBuffers();
- }
}
return result;
}
@@ -698,13 +680,10 @@
Mutex::Autolock lock(mLock);
if (checkPidAndHardware() != NO_ERROR) return;
+
disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
mHardware->stopPreview();
- if (mSurface != 0 && !mUseOverlay) {
- mSurface->unregisterBuffers();
- }
-
mPreviewBuffer.clear();
}
@@ -992,11 +971,6 @@
void CameraService::Client::handleShutter(image_rect_type *size) {
mCameraService->playSound(SOUND_SHUTTER);
- // Screen goes black after the buffer is unregistered.
- if (mSurface != 0 && !mUseOverlay) {
- mSurface->unregisterBuffers();
- }
-
sp<ICameraClient> c = mCameraClient;
if (c != 0) {
mLock.unlock();
@@ -1024,7 +998,6 @@
HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0,
mHardware->getRawHeap());
- mSurface->registerBuffers(buffers);
IPCThreadState::self()->flushCommands();
}
@@ -1037,12 +1010,6 @@
size_t size;
sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
- if (!mUseOverlay) {
- if (mSurface != 0) {
- mSurface->postBuffer(offset);
- }
- }
-
// local copy of the callback flags
int flags = mPreviewCallbackFlag;
@@ -1102,11 +1069,6 @@
size_t size;
sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
- // Put the YUV version of the snapshot in the preview display.
- if (mSurface != 0 && !mUseOverlay) {
- mSurface->postBuffer(offset);
- }
-
sp<ICameraClient> c = mCameraClient;
mLock.unlock();
if (c != 0) {
@@ -1264,4 +1226,12 @@
return NO_ERROR;
}
+sp<ISurface> CameraService::getISurface(const sp<Surface>& surface) {
+ if (surface != 0) {
+ return surface->getISurface();
+ } else {
+ return sp<ISurface>(0);
+ }
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 77ccf41..7ed192e 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -79,6 +79,12 @@
sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS];
int mSoundRef; // reference count (release all MediaPlayer when 0)
+ // Used by Client objects to extract the ISurface from a Surface object.
+ // This is used because making Client a friend class of Surface would
+ // require including this header in Surface.h since Client is a nested
+ // class.
+ static sp<ISurface> getISurface(const sp<Surface>& surface);
+
class Client : public BnCamera
{
public:
@@ -87,7 +93,7 @@
virtual status_t connect(const sp<ICameraClient>& client);
virtual status_t lock();
virtual status_t unlock();
- virtual status_t setPreviewDisplay(const sp<ISurface>& surface);
+ virtual status_t setPreviewDisplay(const sp<Surface>& surface);
virtual void setPreviewCallbackFlag(int flag);
virtual status_t startPreview();
virtual void stopPreview();
@@ -106,6 +112,7 @@
friend class CameraService;
Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
+ const sp<CameraHardwareInterface>& hardware,
int cameraId,
int clientPid);
~Client();
@@ -168,6 +175,7 @@
// Ensures atomicity among the public methods
mutable Mutex mLock;
sp<ISurface> mSurface;
+ sp<ANativeWindow> mPreviewWindow;
// If the user want us to return a copy of the preview frame (instead
// of the original one), we allocate mPreviewBuffer and reuse it if possible.
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 4da0bac..bd2a0eaa6 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -943,7 +943,6 @@
}
Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
if (info.isFailover()) {
intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
@@ -1059,7 +1058,6 @@
private void sendConnectedBroadcast(NetworkInfo info) {
Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
if (info.isFailover()) {
intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
@@ -1097,7 +1095,6 @@
}
Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
if (getActiveNetworkInfo() == null) {
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 9f8557f..8b02355 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -357,7 +357,7 @@
*/
public boolean pingSupplicant() {
enforceAccessPermission();
- return mWifiStateMachine.pingSupplicant();
+ return mWifiStateMachine.syncPingSupplicant();
}
/**
@@ -436,7 +436,7 @@
*/
public int getWifiEnabledState() {
enforceAccessPermission();
- return mWifiStateMachine.getWifiState();
+ return mWifiStateMachine.syncGetWifiState();
}
/**
@@ -481,7 +481,7 @@
*/
public int getWifiApEnabledState() {
enforceAccessPermission();
- return mWifiStateMachine.getWifiApState();
+ return mWifiStateMachine.syncGetWifiApState();
}
/**
@@ -555,7 +555,7 @@
*/
public List<WifiConfiguration> getConfiguredNetworks() {
enforceAccessPermission();
- return mWifiStateMachine.getConfiguredNetworks();
+ return mWifiStateMachine.syncGetConfiguredNetworks();
}
/**
@@ -565,7 +565,7 @@
*/
public int addOrUpdateNetwork(WifiConfiguration config) {
enforceChangePermission();
- return mWifiStateMachine.addOrUpdateNetwork(config);
+ return mWifiStateMachine.syncAddOrUpdateNetwork(config);
}
/**
@@ -576,7 +576,7 @@
*/
public boolean removeNetwork(int netId) {
enforceChangePermission();
- return mWifiStateMachine.removeNetwork(netId);
+ return mWifiStateMachine.syncRemoveNetwork(netId);
}
/**
@@ -588,7 +588,7 @@
*/
public boolean enableNetwork(int netId, boolean disableOthers) {
enforceChangePermission();
- return mWifiStateMachine.enableNetwork(netId, disableOthers);
+ return mWifiStateMachine.syncEnableNetwork(netId, disableOthers);
}
/**
@@ -599,7 +599,7 @@
*/
public boolean disableNetwork(int netId) {
enforceChangePermission();
- return mWifiStateMachine.disableNetwork(netId);
+ return mWifiStateMachine.syncDisableNetwork(netId);
}
/**
@@ -612,7 +612,7 @@
* Make sure we have the latest information, by sending
* a status request to the supplicant.
*/
- return mWifiStateMachine.requestConnectionInfo();
+ return mWifiStateMachine.syncRequestConnectionInfo();
}
/**
@@ -622,7 +622,7 @@
*/
public List<ScanResult> getScanResults() {
enforceAccessPermission();
- return mWifiStateMachine.getScanResultsList();
+ return mWifiStateMachine.syncGetScanResultsList();
}
/**
@@ -634,7 +634,7 @@
public boolean saveConfiguration() {
boolean result = true;
enforceChangePermission();
- return mWifiStateMachine.saveConfig();
+ return mWifiStateMachine.syncSaveConfig();
}
/**
@@ -723,7 +723,7 @@
*/
public DhcpInfo getDhcpInfo() {
enforceAccessPermission();
- return mWifiStateMachine.getDhcpInfo();
+ return mWifiStateMachine.syncGetDhcpInfo();
}
/**
@@ -823,7 +823,7 @@
* or plugged in to AC).
*/
if (!shouldWifiStayAwake(stayAwakeConditions, mPluggedType)) {
- WifiInfo info = mWifiStateMachine.requestConnectionInfo();
+ WifiInfo info = mWifiStateMachine.syncRequestConnectionInfo();
if (info.getSupplicantState() != SupplicantState.COMPLETED) {
// we used to go to sleep immediately, but this caused some race conditions
// we don't have time to track down for this release. Delay instead,
@@ -1002,7 +1002,7 @@
+ ", uid=" + Binder.getCallingUid());
return;
}
- pw.println("Wi-Fi is " + mWifiStateMachine.getWifiStateByName());
+ pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName());
pw.println("Stay-awake conditions: " +
Settings.System.getInt(mContext.getContentResolver(),
Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0));
@@ -1012,7 +1012,7 @@
pw.println(mWifiStateMachine);
pw.println();
pw.println("Latest scan results:");
- List<ScanResult> scanResults = mWifiStateMachine.getScanResultsList();
+ List<ScanResult> scanResults = mWifiStateMachine.syncGetScanResultsList();
if (scanResults != null && scanResults.size() != 0) {
pw.println(" BSSID Frequency RSSI Flags SSID");
for (ScanResult r : scanResults) {
@@ -1320,7 +1320,7 @@
if ((state == NetworkInfo.State.DISCONNECTED)
|| (state == NetworkInfo.State.UNKNOWN)) {
// Look for an open network
- List<ScanResult> scanResults = mWifiStateMachine.getScanResultsList();
+ List<ScanResult> scanResults = mWifiStateMachine.syncGetScanResultsList();
if (scanResults != null) {
int numOpenNetworks = 0;
for (int i = scanResults.size() - 1; i >= 0; i--) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 57f93c4..d5750c6 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -16,11 +16,6 @@
package com.android.server;
-import static android.os.LocalPowerManager.CHEEK_EVENT;
-import static android.os.LocalPowerManager.OTHER_EVENT;
-import static android.os.LocalPowerManager.TOUCH_EVENT;
-import static android.os.LocalPowerManager.LONG_TOUCH_EVENT;
-import static android.os.LocalPowerManager.TOUCH_UP_EVENT;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
@@ -76,7 +71,6 @@
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
-import android.os.LatencyTimer;
import android.os.LocalPowerManager;
import android.os.Looper;
import android.os.Message;
@@ -109,13 +103,11 @@
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
-import android.view.InputQueue;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceSession;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
@@ -127,9 +119,13 @@
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
+import java.io.BufferedReader;
import java.io.BufferedWriter;
+import java.io.DataInputStream;
import java.io.File;
import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
@@ -164,8 +160,6 @@
static final boolean DEBUG_WALLPAPER = false;
static final boolean SHOW_TRANSACTIONS = false;
static final boolean HIDE_STACK_CRAWLS = true;
- static final boolean MEASURE_LATENCY = false;
- static private LatencyTimer lt;
static final boolean PROFILE_ORIENTATION = false;
static final boolean BLUR = true;
@@ -603,10 +597,6 @@
private WindowManagerService(Context context, PowerManagerService pm,
boolean haveInputMethods) {
- if (MEASURE_LATENCY) {
- lt = new LatencyTimer(100, 1000);
- }
-
mContext = context;
mHaveInputMethods = haveInputMethods;
mLimitedAlphaCompositing = context.getResources().getBoolean(
@@ -9582,6 +9572,10 @@
Surface.closeTransaction();
+ if (mWatermark != null) {
+ mWatermark.drawIfNeeded();
+ }
+
if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
"With display frozen, orientationChangeComplete="
+ orientationChangeComplete);
@@ -10067,12 +10061,17 @@
mScreenFrozenLock.release();
}
- static int getPropertyInt(String name, int defUnits, int defDps, DisplayMetrics dm) {
- String str = SystemProperties.get(name);
- try {
- int val = Integer.parseInt(str);
- return val;
- } catch (Exception e) {
+ static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
+ DisplayMetrics dm) {
+ if (index < tokens.length) {
+ String str = tokens[index];
+ if (str != null && str.length() > 0) {
+ try {
+ int val = Integer.parseInt(str);
+ return val;
+ } catch (Exception e) {
+ }
+ }
}
if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
return defDps;
@@ -10082,62 +10081,142 @@
}
class Watermark {
- Surface mSurface;
- int mWidth;
- int mHeight;
- int mXPercent;
- int mYPercent;
+ final String[] mTokens;
+ final String mText;
+ final Paint mTextPaint;
+ final int mTextWidth;
+ final int mTextHeight;
+ final int mTextAscent;
+ final int mTextDescent;
+ final int mDeltaX;
+ final int mDeltaY;
- Watermark(SurfaceSession session, String text) {
+ Surface mSurface;
+ int mLastDW;
+ int mLastDH;
+ boolean mDrawNeeded;
+
+ Watermark(SurfaceSession session, String[] tokens) {
final DisplayMetrics dm = new DisplayMetrics();
mDisplay.getMetrics(dm);
- int fontSize = getPropertyInt("ro.watermark.height",
- TypedValue.COMPLEX_UNIT_DIP, 48, dm);
- mXPercent = getPropertyInt("ro.watermark.x",
- TypedValue.COMPLEX_UNIT_PX, 50, dm);
- mYPercent = getPropertyInt("ro.watermark.y",
- TypedValue.COMPLEX_UNIT_PX, 99, dm);
- int color = getPropertyInt("ro.watermark.color",
- TypedValue.COMPLEX_UNIT_PX, 0x80ffffff, dm);
- int shadowRadius = getPropertyInt("ro.watermark.shadow.radius",
- TypedValue.COMPLEX_UNIT_PX, 5, dm);
- int shadowDx = getPropertyInt("ro.watermark.shadow.dx",
- TypedValue.COMPLEX_UNIT_PX, 0, dm);
- int shadowDy = getPropertyInt("ro.watermark.shadow.dy",
- TypedValue.COMPLEX_UNIT_PX, 0, dm);
- int shadowColor = getPropertyInt("ro.watermark.shadow.color",
- TypedValue.COMPLEX_UNIT_PX, 0xff000000, dm);
+ if (false) {
+ Log.i(TAG, "*********************** WATERMARK");
+ for (int i=0; i<tokens.length; i++) {
+ Log.i(TAG, " TOKEN #" + i + ": " + tokens[i]);
+ }
+ }
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setTextSize(fontSize);
- paint.setColor(color);
- paint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
- paint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD));
+ mTokens = tokens;
- FontMetricsInt fm = paint.getFontMetricsInt();
- mHeight = fm.descent - fm.ascent + 20;
- mWidth = (int)paint.measureText(text) + 20;
+ StringBuilder builder = new StringBuilder(32);
+ int len = mTokens[0].length();
+ len = len & ~1;
+ for (int i=0; i<len; i+=2) {
+ int c1 = mTokens[0].charAt(i);
+ int c2 = mTokens[0].charAt(i+1);
+ if (c1 >= 'a' && c1 <= 'f') c1 = c1 - 'a' + 10;
+ else if (c1 >= 'A' && c1 <= 'F') c1 = c1 - 'A' + 10;
+ else c1 -= '0';
+ if (c2 >= 'a' && c2 <= 'f') c2 = c2 - 'a' + 10;
+ else if (c2 >= 'A' && c2 <= 'F') c2 = c2 - 'A' + 10;
+ else c2 -= '0';
+ builder.append((char)(255-((c1*16)+c2)));
+ }
+ mText = builder.toString();
+ if (false) {
+ Log.i(TAG, "Final text: " + mText);
+ }
+
+ int fontSize = getPropertyInt(tokens, 1,
+ TypedValue.COMPLEX_UNIT_DIP, 20, dm);
+
+ mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mTextPaint.setTextSize(fontSize);
+ mTextPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD));
+
+ FontMetricsInt fm = mTextPaint.getFontMetricsInt();
+ mTextWidth = (int)mTextPaint.measureText(mText);
+ mTextAscent = fm.ascent;
+ mTextDescent = fm.descent;
+ mTextHeight = fm.descent - fm.ascent;
+
+ mDeltaX = getPropertyInt(tokens, 2,
+ TypedValue.COMPLEX_UNIT_PX, mTextWidth*2, dm);
+ mDeltaY = getPropertyInt(tokens, 3,
+ TypedValue.COMPLEX_UNIT_PX, mTextHeight*3, dm);
+ int shadowColor = getPropertyInt(tokens, 4,
+ TypedValue.COMPLEX_UNIT_PX, 0xb0000000, dm);
+ int color = getPropertyInt(tokens, 5,
+ TypedValue.COMPLEX_UNIT_PX, 0x60ffffff, dm);
+ int shadowRadius = getPropertyInt(tokens, 6,
+ TypedValue.COMPLEX_UNIT_PX, 7, dm);
+ int shadowDx = getPropertyInt(tokens, 8,
+ TypedValue.COMPLEX_UNIT_PX, 0, dm);
+ int shadowDy = getPropertyInt(tokens, 9,
+ TypedValue.COMPLEX_UNIT_PX, 0, dm);
+
+ mTextPaint.setColor(color);
+ mTextPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
try {
mSurface = new Surface(session, 0,
- "WatermarkSurface",
- -1, mWidth, mHeight, PixelFormat.TRANSLUCENT, 0);
+ "WatermarkSurface", -1, 1, 1, PixelFormat.TRANSLUCENT, 0);
mSurface.setLayer(TYPE_LAYER_MULTIPLIER*100);
- Rect dirty = new Rect(0, 0, mWidth, mHeight);
- Canvas c = mSurface.lockCanvas(dirty);
- c.drawText(text, 10, -fm.ascent+10, paint);
- mSurface.unlockCanvasAndPost(c);
+ mSurface.setPosition(0, 0);
mSurface.show();
} catch (OutOfResourcesException e) {
}
}
void positionSurface(int dw, int dh) {
- int availW = dw - mWidth;
- int availH = dh - mHeight;
- mSurface.setPosition((availW*mXPercent)/100,
- (availH*mYPercent)/100);
+ if (mLastDW != dw || mLastDH != dh) {
+ mLastDW = dw;
+ mLastDH = dh;
+ mSurface.setSize(dw, dh);
+ mDrawNeeded = true;
+ }
+ }
+
+ void drawIfNeeded() {
+ if (mDrawNeeded) {
+ final int dw = mLastDW;
+ final int dh = mLastDH;
+
+ mDrawNeeded = false;
+ Rect dirty = new Rect(0, 0, dw, dh);
+ Canvas c = null;
+ try {
+ c = mSurface.lockCanvas(dirty);
+ } catch (IllegalArgumentException e) {
+ } catch (OutOfResourcesException e) {
+ }
+ if (c != null) {
+ int deltaX = mDeltaX;
+ int deltaY = mDeltaY;
+
+ // deltaX shouldn't be close to a round fraction of our
+ // x step, or else things will line up too much.
+ int div = (dw+mTextWidth)/deltaX;
+ int rem = (dw+mTextWidth) - (div*deltaX);
+ int qdelta = deltaX/4;
+ if (rem < qdelta || rem > (deltaX-qdelta)) {
+ deltaX += deltaX/3;
+ }
+
+ int y = -mTextHeight;
+ int x = -mTextWidth;
+ while (y < (dh+mTextHeight)) {
+ c.drawText(mText, x, y, mTextPaint);
+ x += deltaX;
+ if (x >= dw) {
+ x -= (dw+mTextWidth);
+ y += deltaY;
+ }
+ }
+ mSurface.unlockCanvasAndPost(c);
+ }
+ }
}
}
@@ -10146,12 +10225,28 @@
return;
}
- String text = SystemProperties.get("ro.watermark.text");
- if (text == null || text.length() <= 0) {
- return;
+ File file = new File("/system/etc/setup.conf");
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream(file);
+ DataInputStream ind = new DataInputStream(in);
+ String line = ind.readLine();
+ if (line != null) {
+ String[] toks = line.split("%");
+ if (toks != null && toks.length > 0) {
+ mWatermark = new Watermark(mFxSession, toks);
+ }
+ }
+ } catch (FileNotFoundException e) {
+ } catch (IOException e) {
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
}
-
- mWatermark = new Watermark(mFxSession, text);
}
@Override
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 63746e7b..56159b5 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4100,16 +4100,23 @@
}
}
- void grantUriPermissionLocked(int callingUid,
- String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) {
+ /**
+ * Check if the targetPkg can be granted permission to access uri by
+ * the callingUid using the given modeFlags. Throws a security exception
+ * if callingUid is not allowed to do this. Returns the uid of the target
+ * if the URI permission grant should be performed; returns -1 if it is not
+ * needed (for example targetPkg already has permission to access the URI).
+ */
+ int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
+ Uri uri, int modeFlags) {
modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
if (modeFlags == 0) {
- return;
+ return -1;
}
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
- "Requested grant " + targetPkg + " permission to " + uri);
+ "Checking grant " + targetPkg + " permission to " + uri);
final IPackageManager pm = AppGlobals.getPackageManager();
@@ -4117,7 +4124,7 @@
if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"Can't grant URI permission for non-content URI: " + uri);
- return;
+ return -1;
}
String name = uri.getAuthority();
@@ -4134,7 +4141,7 @@
}
if (pi == null) {
Slog.w(TAG, "No content provider found for: " + name);
- return;
+ return -1;
}
int targetUid;
@@ -4143,10 +4150,10 @@
if (targetUid < 0) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"Can't grant URI permission no uid for: " + targetPkg);
- return;
+ return -1;
}
} catch (RemoteException ex) {
- return;
+ return -1;
}
// First... does the target actually need this permission?
@@ -4154,7 +4161,7 @@
// No need to grant the target this permission.
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"Target " + targetPkg + " already has full permission to " + uri);
- return;
+ return -1;
}
// Second... is the provider allowing granting of URI permissions?
@@ -4191,12 +4198,23 @@
}
}
- // Okay! So here we are: the caller has the assumed permission
+ return targetUid;
+ }
+
+ void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
+ Uri uri, int modeFlags, UriPermissionOwner owner) {
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ if (modeFlags == 0) {
+ return;
+ }
+
+ // So here we are: the caller has the assumed permission
// to the uri, and the target doesn't. Let's now give this to
// the target.
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
- "Granting " + targetPkg + " permission to " + uri);
+ "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
HashMap<Uri, UriPermission> targetUris
= mGrantedUriPermissions.get(targetUid);
@@ -4212,39 +4230,65 @@
}
perm.modeFlags |= modeFlags;
- if (activity == null) {
+ if (owner == null) {
perm.globalModeFlags |= modeFlags;
} else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
- perm.readActivities.add(activity);
- if (activity.readUriPermissions == null) {
- activity.readUriPermissions = new HashSet<UriPermission>();
- }
- activity.readUriPermissions.add(perm);
+ perm.readOwners.add(owner);
+ owner.addReadPermission(perm);
} else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
- perm.writeActivities.add(activity);
- if (activity.writeUriPermissions == null) {
- activity.writeUriPermissions = new HashSet<UriPermission>();
- }
- activity.writeUriPermissions.add(perm);
+ perm.writeOwners.add(owner);
+ owner.addWritePermission(perm);
}
}
- void grantUriPermissionFromIntentLocked(int callingUid,
- String targetPkg, Intent intent, ActivityRecord activity) {
+ void grantUriPermissionLocked(int callingUid,
+ String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
+ int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
+ if (targetUid < 0) {
+ return;
+ }
+
+ grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
+ }
+
+ /**
+ * Like checkGrantUriPermissionLocked, but takes an Intent.
+ */
+ int checkGrantUriPermissionFromIntentLocked(int callingUid,
+ String targetPkg, Intent intent) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
- "Grant URI perm to " + (intent != null ? intent.getData() : null)
+ "Checking URI perm to " + (intent != null ? intent.getData() : null)
+ " from " + intent + "; flags=0x"
+ Integer.toHexString(intent != null ? intent.getFlags() : 0));
if (intent == null) {
- return;
+ return -1;
}
Uri data = intent.getData();
if (data == null) {
+ return -1;
+ }
+ return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
+ intent.getFlags());
+ }
+
+ /**
+ * Like grantUriPermissionUncheckedLocked, but takes an Intent.
+ */
+ void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
+ String targetPkg, Intent intent, UriPermissionOwner owner) {
+ grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
+ intent.getFlags(), owner);
+ }
+
+ void grantUriPermissionFromIntentLocked(int callingUid,
+ String targetPkg, Intent intent, UriPermissionOwner owner) {
+ int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
+ if (targetUid < 0) {
return;
}
- grantUriPermissionLocked(callingUid, targetPkg, data,
- intent.getFlags(), activity);
+
+ grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
}
public void grantUriPermission(IApplicationThread caller, String targetPkg,
@@ -8215,18 +8259,23 @@
return;
}
- int i = 0;
- while (i < N) {
+ while (r.pendingStarts.size() > 0) {
try {
- ServiceRecord.StartItem si = r.pendingStarts.get(i);
+ 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 (si.intent == null && N > 1) {
+ if (si.intent == null) {
// If somehow we got a dummy start at the front, then
// just drop it here.
- i++;
continue;
}
+ si.deliveredTime = SystemClock.uptimeMillis();
+ r.deliveredStarts.add(si);
+ si.deliveryCount++;
+ if (si.targetPermissionUid >= 0) {
+ grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
+ r.packageName, si.intent, si);
+ }
bumpServiceExecutingLocked(r);
if (!oomAdjusted) {
oomAdjusted = true;
@@ -8240,10 +8289,6 @@
flags |= Service.START_FLAG_REDELIVERY;
}
r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
- si.deliveredTime = SystemClock.uptimeMillis();
- r.deliveredStarts.add(si);
- si.deliveryCount++;
- i++;
} catch (RemoteException e) {
// Remote process gone... we'll let the normal cleanup take
// care of this.
@@ -8253,14 +8298,6 @@
break;
}
}
- if (i == N) {
- r.pendingStarts.clear();
- } else {
- while (i > 0) {
- i--;
- r.pendingStarts.remove(i);
- }
- }
}
private final boolean requestServiceBindingLocked(ServiceRecord r,
@@ -8343,7 +8380,7 @@
if (r.lastStartId < 1) {
r.lastStartId = 1;
}
- r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
+ r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
}
sendServiceArgsLocked(r, true);
@@ -8363,6 +8400,7 @@
if (N > 0) {
for (int i=N-1; i>=0; i--) {
ServiceRecord.StartItem si = r.deliveredStarts.get(i);
+ si.removeUriPermissionsLocked();
if (si.intent == null) {
// We'll generate this again if needed.
} else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
@@ -8602,7 +8640,7 @@
r.foregroundNoti = null;
// Clear start entries.
- r.deliveredStarts.clear();
+ r.clearDeliveredStartsLocked();
r.pendingStarts.clear();
if (r.app != null) {
@@ -8662,6 +8700,8 @@
? res.permission : "private to package");
}
ServiceRecord r = res.record;
+ int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
+ callingUid, r.packageName, service);
if (unscheduleServiceRestartLocked(r)) {
if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
+ r.shortName);
@@ -8672,7 +8712,8 @@
if (r.lastStartId < 1) {
r.lastStartId = 1;
}
- r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
+ r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
+ service, targetPermissionUid));
r.lastActivity = SystemClock.uptimeMillis();
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
@@ -8797,7 +8838,9 @@
ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
if (si != null) {
while (r.deliveredStarts.size() > 0) {
- if (r.deliveredStarts.remove(0) == si) {
+ ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
+ cur.removeUriPermissionsLocked();
+ if (cur == si) {
break;
}
}
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 79756a7..80a41b7 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -29,6 +29,7 @@
import android.os.Bundle;
import android.os.Message;
import android.os.Process;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.util.EventLog;
import android.util.Log;
@@ -43,7 +44,7 @@
/**
* An entry in the history stack, representing an activity.
*/
-class ActivityRecord extends IApplicationToken.Stub {
+class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwner {
final ActivityManagerService service; // owner
final ActivityStack stack; // owner
final ActivityInfo info; // all about me
@@ -340,16 +341,22 @@
* Deliver a new Intent to an existing activity, so that its onNewIntent()
* method will be called at the proper time.
*/
- final void deliverNewIntentLocked(Intent intent) {
+ final void deliverNewIntentLocked(int callingUid, Intent intent) {
boolean sent = false;
if (state == ActivityState.RESUMED
&& app != null && app.thread != null) {
try {
ArrayList<Intent> ar = new ArrayList<Intent>();
- ar.add(new Intent(intent));
+ intent = new Intent(intent);
+ ar.add(intent);
+ service.grantUriPermissionFromIntentLocked(callingUid, packageName,
+ intent, this);
app.thread.scheduleNewIntent(ar, this);
sent = true;
- } catch (Exception e) {
+ } catch (RemoteException e) {
+ Slog.w(ActivityManagerService.TAG,
+ "Exception thrown sending new intent to " + this, e);
+ } catch (NullPointerException e) {
Slog.w(ActivityManagerService.TAG,
"Exception thrown sending new intent to " + this, e);
}
@@ -362,23 +369,25 @@
void removeUriPermissionsLocked() {
if (readUriPermissions != null) {
for (UriPermission perm : readUriPermissions) {
- perm.readActivities.remove(this);
- if (perm.readActivities.size() == 0 && (perm.globalModeFlags
+ 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);
+ service.removeUriPermissionIfNeededLocked(perm);
}
}
+ readUriPermissions = null;
}
if (writeUriPermissions != null) {
for (UriPermission perm : writeUriPermissions) {
- perm.writeActivities.remove(this);
- if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
+ 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;
}
}
@@ -569,6 +578,37 @@
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) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index de7b15c..a5f7e96 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -2033,16 +2033,6 @@
}
}
- if (grantedUriPermissions != null && callingUid > 0) {
- for (int i=0; i<grantedUriPermissions.length; i++) {
- mService.grantUriPermissionLocked(callingUid, r.packageName,
- grantedUriPermissions[i], grantedMode, r);
- }
- }
-
- mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
- intent, r);
-
if (sourceRecord == null) {
// This activity is not being started from another... in this
// case we -always- start a new task.
@@ -2150,7 +2140,7 @@
top.task.setIntent(r.intent, r.info);
}
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
- top.deliverNewIntentLocked(r.intent);
+ top.deliverNewIntentLocked(callingUid, r.intent);
} else {
// A special case: we need to
// start the activity because it is not currently
@@ -2175,7 +2165,7 @@
if (taskTop.frontOfTask) {
taskTop.task.setIntent(r.intent, r.info);
}
- taskTop.deliverNewIntentLocked(r.intent);
+ taskTop.deliverNewIntentLocked(callingUid, r.intent);
} else if (!r.intent.filterEquals(taskTop.task.intent)) {
// In this case we are launching the root activity
// of the task, but with a different intent. We
@@ -2243,7 +2233,7 @@
// is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
- top.deliverNewIntentLocked(r.intent);
+ top.deliverNewIntentLocked(callingUid, r.intent);
return START_DELIVERED_TO_TOP;
}
}
@@ -2288,7 +2278,7 @@
sourceRecord.task.taskId, r, launchFlags, true);
if (top != null) {
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
- top.deliverNewIntentLocked(r.intent);
+ top.deliverNewIntentLocked(callingUid, r.intent);
// For paranoia, make sure we have correctly
// resumed the top activity.
if (doResume) {
@@ -2305,7 +2295,7 @@
if (where >= 0) {
ActivityRecord top = moveActivityToFrontLocked(where);
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
- top.deliverNewIntentLocked(r.intent);
+ top.deliverNewIntentLocked(callingUid, r.intent);
if (doResume) {
resumeTopActivityLocked(null);
}
@@ -2333,6 +2323,17 @@
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in new guessed " + r.task);
}
+
+ if (grantedUriPermissions != null && callingUid > 0) {
+ for (int i=0; i<grantedUriPermissions.length; i++) {
+ mService.grantUriPermissionLocked(callingUid, r.packageName,
+ grantedUriPermissions[i], grantedMode, r);
+ }
+ }
+
+ mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
+ intent, r);
+
if (newTask) {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
}
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index c3f0b3e..bac21b1 100644
--- a/services/java/com/android/server/am/BroadcastRecord.java
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -26,6 +26,7 @@
import android.os.IBinder;
import android.os.SystemClock;
import android.util.PrintWriterPrinter;
+import android.util.TimeUtils;
import java.io.PrintWriter;
import java.util.List;
@@ -73,61 +74,65 @@
ActivityInfo curReceiver; // info about the receiver that is currently running.
void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + this);
- pw.println(prefix + intent);
+ final long now = SystemClock.uptimeMillis();
+
+ pw.print(prefix); pw.println(this);
+ pw.print(prefix); pw.println(intent);
if (sticky) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
- pw.println(prefix + "extras: " + bundle.toString());
+ pw.print(prefix); pw.print("extras: "); pw.println(bundle.toString());
}
}
- pw.println(prefix + "proc=" + callerApp);
- pw.println(prefix + "caller=" + callerPackage
- + " callingPid=" + callingPid
- + " callingUid=" + callingUid);
+ pw.print(prefix); pw.print("caller="); pw.print(callerPackage); pw.println(" ");
+ pw.println(callerApp != null ? callerApp.toShortString() : "null");
+ pw.print(" pid="); pw.print(callingPid);
+ pw.print(" uid="); pw.println(callingUid);
if (requiredPermission != null) {
- pw.println(prefix + "requiredPermission=" + requiredPermission);
+ pw.print(prefix); pw.print("requiredPermission="); pw.println(requiredPermission);
}
- pw.println(prefix + "dispatchTime=" + dispatchTime + " ("
- + (SystemClock.uptimeMillis()-dispatchTime) + "ms since now)");
+ pw.print(prefix); pw.print("dispatchTime=");
+ TimeUtils.formatDuration(dispatchTime, now, pw);
if (finishTime != 0) {
- pw.println(prefix + "finishTime=" + finishTime + " ("
- + (SystemClock.uptimeMillis()-finishTime) + "ms since now)");
+ pw.print(" finishTime="); TimeUtils.formatDuration(finishTime, now, pw);
} else {
- pw.println(prefix + "receiverTime=" + receiverTime + " ("
- + (SystemClock.uptimeMillis()-receiverTime) + "ms since now)");
+ pw.print(" receiverTime="); TimeUtils.formatDuration(receiverTime, now, pw);
}
+ pw.println("");
if (anrCount != 0) {
- pw.println(prefix + "anrCount=" + anrCount);
+ pw.print(prefix); pw.print("anrCount="); pw.println(anrCount);
}
if (resultTo != null || resultCode != -1 || resultData != null) {
- pw.println(prefix + "resultTo=" + resultTo
- + " resultCode=" + resultCode + " resultData=" + resultData);
+ pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
+ pw.print(" resultCode="); pw.print(resultCode);
+ pw.print(" resultData="); pw.println(resultData);
}
if (resultExtras != null) {
- pw.println(prefix + "resultExtras=" + resultExtras);
+ pw.print(prefix); pw.print("resultExtras="); pw.println(resultExtras);
}
if (resultAbort || ordered || sticky || initialSticky) {
- pw.println(prefix + "resultAbort=" + resultAbort
- + " ordered=" + ordered + " sticky=" + sticky
- + " initialSticky=" + initialSticky);
+ pw.print(prefix); pw.print("resultAbort="); pw.print(resultAbort);
+ pw.print(" ordered="); pw.print(ordered);
+ pw.print(" sticky="); pw.print(sticky);
+ pw.print(" initialSticky="); pw.println(initialSticky);
}
if (nextReceiver != 0 || receiver != null) {
- pw.println(prefix + "nextReceiver=" + nextReceiver
- + " receiver=" + receiver);
+ pw.print(prefix); pw.print("nextReceiver="); pw.print(nextReceiver);
+ pw.print(" receiver="); pw.println(receiver);
}
if (curFilter != null) {
- pw.println(prefix + "curFilter=" + curFilter);
+ pw.print(prefix); pw.print("curFilter="); pw.println(curFilter);
}
if (curReceiver != null) {
- pw.println(prefix + "curReceiver=" + curReceiver);
+ pw.print(prefix); pw.print("curReceiver="); pw.println(curReceiver);
}
if (curApp != null) {
- pw.println(prefix + "curApp=" + curApp);
- pw.println(prefix + "curComponent="
- + (curComponent != null ? curComponent.toShortString() : "--"));
+ pw.print(prefix); pw.print("curApp="); pw.println(curApp);
+ pw.print(prefix); pw.print("curComponent=");
+ pw.println((curComponent != null ? curComponent.toShortString() : "--"));
if (curReceiver != null && curReceiver.applicationInfo != null) {
- pw.println(prefix + "curSourceDir=" + curReceiver.applicationInfo.sourceDir);
+ pw.print(prefix); pw.print("curSourceDir=");
+ pw.println(curReceiver.applicationInfo.sourceDir);
}
}
String stateStr = " (?)";
@@ -137,13 +142,14 @@
case CALL_IN_RECEIVE: stateStr=" (CALL_IN_RECEIVE)"; break;
case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_RECEIVE)"; break;
}
- pw.println(prefix + "state=" + state + stateStr);
+ pw.print(prefix); pw.print("state="); pw.print(state); pw.println(stateStr);
final int N = receivers != null ? receivers.size() : 0;
String p2 = prefix + " ";
PrintWriterPrinter printer = new PrintWriterPrinter(pw);
for (int i=0; i<N; i++) {
Object o = receivers.get(i);
- pw.println(prefix + "Receiver #" + i + ": " + o);
+ pw.print(prefix); pw.print("Receiver #"); pw.print(i);
+ pw.print(": "); pw.println(o);
if (o instanceof BroadcastFilter)
((BroadcastFilter)o).dumpBrief(pw, p2);
else if (o instanceof ResolveInfo)
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index ab5a78d..255fbe3 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -36,6 +36,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -43,6 +44,12 @@
* A running application service.
*/
class ServiceRecord extends Binder {
+ // Maximum number of delivery attempts before giving up.
+ static final int MAX_DELIVERY_COUNT = 3;
+
+ // Maximum number of times it can fail during execution before giving up.
+ static final int MAX_DONE_EXECUTING_COUNT = 6;
+
final ActivityManagerService ams;
final BatteryStatsImpl.Uid.Pkg.Serv stats;
final ComponentName name; // service component.
@@ -68,29 +75,6 @@
final HashMap<IBinder, ConnectionRecord> connections
= new HashMap<IBinder, ConnectionRecord>();
// IBinder -> ConnectionRecord of all bound clients
-
- // Maximum number of delivery attempts before giving up.
- static final int MAX_DELIVERY_COUNT = 3;
-
- // Maximum number of times it can fail during execution before giving up.
- static final int MAX_DONE_EXECUTING_COUNT = 6;
-
- static class StartItem {
- final int id;
- final Intent intent;
- long deliveredTime;
- int deliveryCount;
- int doneExecutingCount;
-
- StartItem(int _id, Intent _intent) {
- id = _id;
- intent = _intent;
- }
- }
- final ArrayList<StartItem> deliveredStarts = new ArrayList<StartItem>();
- // start() arguments which been delivered.
- final ArrayList<StartItem> pendingStarts = new ArrayList<StartItem>();
- // start() arguments that haven't yet been delivered.
ProcessRecord app; // where this service is running or null.
boolean isForeground; // is service currently in foreground mode?
@@ -112,6 +96,104 @@
String stringName; // caching of toString
+ static class StartItem implements UriPermissionOwner {
+ final ServiceRecord sr;
+ final int id;
+ final Intent intent;
+ final int targetPermissionUid;
+ long deliveredTime;
+ int deliveryCount;
+ int doneExecutingCount;
+
+ 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;
+ intent = _intent;
+ targetPermissionUid = _targetPermissionUid;
+ }
+
+ 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;
+ }
+ }
+
+ public String toString() {
+ if (stringName != null) {
+ return stringName;
+ }
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("ServiceRecord{")
+ .append(Integer.toHexString(System.identityHashCode(sr)))
+ .append(' ').append(sr.shortName)
+ .append(" StartItem ")
+ .append(Integer.toHexString(System.identityHashCode(this)))
+ .append(" id=").append(id).append('}');
+ return stringName = sb.toString();
+ }
+ }
+
+ final ArrayList<StartItem> deliveredStarts = new ArrayList<StartItem>();
+ // start() arguments which been delivered.
+ final ArrayList<StartItem> pendingStarts = new ArrayList<StartItem>();
+ // start() arguments that haven't yet been delivered.
+
void dumpStartList(PrintWriter pw, String prefix, List<StartItem> list, long now) {
final int N = list.size();
for (int i=0; i<N; i++) {
@@ -128,9 +210,22 @@
if (si.doneExecutingCount != 0) {
pw.print(" dxc="); pw.print(si.doneExecutingCount);
}
- pw.print(" ");
+ pw.println("");
+ pw.print(prefix); pw.print(" intent=");
if (si.intent != null) pw.println(si.intent.toString());
else pw.println("null");
+ if (si.targetPermissionUid >= 0) {
+ 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);
+ }
}
}
@@ -324,6 +419,13 @@
}
}
+ public void clearDeliveredStartsLocked() {
+ for (int i=deliveredStarts.size()-1; i>=0; i--) {
+ deliveredStarts.get(i).removeUriPermissionsLocked();
+ }
+ deliveredStarts.clear();
+ }
+
public String toString() {
if (stringName != null) {
return stringName;
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
index 81450c5..93c59cc 100644
--- a/services/java/com/android/server/am/UriPermission.java
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -22,13 +22,20 @@
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);
+}
+
class UriPermission {
final int uid;
final Uri uri;
int modeFlags = 0;
int globalModeFlags = 0;
- final HashSet<ActivityRecord> readActivities = new HashSet<ActivityRecord>();
- final HashSet<ActivityRecord> writeActivities = new HashSet<ActivityRecord>();
+ final HashSet<UriPermissionOwner> readOwners = new HashSet<UriPermissionOwner>();
+ final HashSet<UriPermissionOwner> writeOwners = new HashSet<UriPermissionOwner>();
String stringName;
@@ -41,27 +48,21 @@
if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
globalModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
- if (readActivities.size() > 0) {
- for (ActivityRecord r : readActivities) {
- r.readUriPermissions.remove(this);
- if (r.readUriPermissions.size() == 0) {
- r.readUriPermissions = null;
- }
+ if (readOwners.size() > 0) {
+ for (UriPermissionOwner r : readOwners) {
+ r.removeReadPermission(this);
}
- readActivities.clear();
+ readOwners.clear();
}
}
if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
- if (readActivities.size() > 0) {
- for (ActivityRecord r : readActivities) {
- r.writeUriPermissions.remove(this);
- if (r.writeUriPermissions.size() == 0) {
- r.writeUriPermissions = null;
- }
+ if (readOwners.size() > 0) {
+ for (UriPermissionOwner r : writeOwners) {
+ r.removeWritePermission(this);
}
- readActivities.clear();
+ readOwners.clear();
}
}
}
@@ -85,11 +86,17 @@
pw.print(" uid="); pw.print(uid);
pw.print(" globalModeFlags=0x");
pw.println(Integer.toHexString(globalModeFlags));
- if (readActivities.size() != 0) {
- pw.print(prefix); pw.print("readActivities="); pw.println(readActivities);
+ if (readOwners.size() != 0) {
+ pw.print(prefix); pw.println("readOwners:");
+ for (UriPermissionOwner owner : readOwners) {
+ pw.print(prefix); pw.print(" * "); pw.println(owner);
+ }
}
- if (writeActivities.size() != 0) {
- pw.print(prefix); pw.print("writeActivities="); pw.println(writeActivities);
+ if (writeOwners.size() != 0) {
+ pw.print(prefix); pw.println("writeOwners:");
+ for (UriPermissionOwner owner : writeOwners) {
+ pw.print(prefix); pw.print(" * "); pw.println(owner);
+ }
}
}
}
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 949b874..53ce5c0 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -34,6 +34,7 @@
import android.net.NetworkInfo;
import android.os.Binder;
import android.os.Environment;
+import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.INetworkManagementService;
@@ -114,6 +115,14 @@
private boolean mUsbMassStorageOff; // track the status of USB Mass Storage
private boolean mUsbConnected; // track the status of USB connection
+ // mUsbHandler message
+ static final int USB_STATE_CHANGE = 1;
+ static final int USB_DISCONNECTED = 0;
+ static final int USB_CONNECTED = 1;
+
+ // Time to delay before processing USB disconnect events
+ static final long USB_DISCONNECT_DELAY = 1000;
+
public Tethering(Context context, Looper looper) {
Log.d(TAG, "Tethering starting");
mContext = context;
@@ -453,12 +462,25 @@
}
}
+ private Handler mUsbHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ mUsbConnected = (msg.arg1 == USB_CONNECTED);
+ updateUsbStatus();
+ }
+ };
+
private class StateReceiver extends BroadcastReceiver {
public void onReceive(Context content, Intent intent) {
String action = intent.getAction();
if (action.equals(Usb.ACTION_USB_STATE)) {
- mUsbConnected = intent.getExtras().getBoolean(Usb.USB_CONNECTED);
- updateUsbStatus();
+ // process connect events immediately, but delay handling disconnects
+ // to debounce USB configuration changes
+ boolean connected = intent.getExtras().getBoolean(Usb.USB_CONNECTED);
+ Message msg = Message.obtain(mUsbHandler, USB_STATE_CHANGE,
+ (connected ? USB_CONNECTED : USB_DISCONNECTED), 0);
+ mUsbHandler.removeMessages(USB_STATE_CHANGE);
+ mUsbHandler.sendMessageDelayed(msg, connected ? 0 : USB_DISCONNECT_DELAY);
} else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
mUsbMassStorageOff = false;
updateUsbStatus();
diff --git a/services/java/com/android/server/sip/SipSessionGroup.java b/services/java/com/android/server/sip/SipSessionGroup.java
index db3f536..d33558b 100644
--- a/services/java/com/android/server/sip/SipSessionGroup.java
+++ b/services/java/com/android/server/sip/SipSessionGroup.java
@@ -381,14 +381,29 @@
: listener);
}
+ // process the command in a new thread
+ private void doCommandAsync(final EventObject command) {
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ processCommand(command);
+ } catch (SipException e) {
+ // TODO: find a better way to do this
+ if ((command instanceof RegisterCommand)
+ || (command == DEREGISTER)) {
+ onRegistrationFailed(e);
+ } else {
+ onError(e);
+ }
+ }
+ }
+ }).start();
+ }
+
public void makeCall(SipProfile peerProfile,
SessionDescription sessionDescription) {
- try {
- processCommand(
- new MakeCallCommand(peerProfile, sessionDescription));
- } catch (SipException e) {
- onError(e);
- }
+ doCommandAsync(
+ new MakeCallCommand(peerProfile, sessionDescription));
}
public void answerCall(SessionDescription sessionDescription) {
@@ -401,36 +416,20 @@
}
public void endCall() {
- try {
- processCommand(END_CALL);
- } catch (SipException e) {
- onError(e);
- }
+ doCommandAsync(END_CALL);
}
public void changeCall(SessionDescription sessionDescription) {
- try {
- processCommand(
- new MakeCallCommand(mPeerProfile, sessionDescription));
- } catch (SipException e) {
- onError(e);
- }
+ doCommandAsync(
+ new MakeCallCommand(mPeerProfile, sessionDescription));
}
public void register(int duration) {
- try {
- processCommand(new RegisterCommand(duration));
- } catch (SipException e) {
- onRegistrationFailed(e);
- }
+ doCommandAsync(new RegisterCommand(duration));
}
public void unregister() {
- try {
- processCommand(DEREGISTER);
- } catch (SipException e) {
- onRegistrationFailed(e);
- }
+ doCommandAsync(DEREGISTER);
}
public boolean isReRegisterRequired() {
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 79772ed..e4825d0 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -22,7 +22,7 @@
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
ifeq ($(TARGET_BOARD_PLATFORM), omap3)
- LOCAL_CFLAGS += -DNO_RGBX_8888
+ LOCAL_CFLAGS += -DNO_RGBX_8888 -DHAS_PUSH_BUFFERS
endif
# need "-lrt" on Linux simulator to pick up clock_gettime
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index d257897..a78d9b9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -165,7 +165,7 @@
{
const nsecs_t now = systemTime();
const nsecs_t duration = now - mBootTime;
- LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
+ LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
mBootFinished = true;
property_set("ctl.stop", "bootanim");
}
@@ -201,10 +201,10 @@
mServerHeap = new MemoryHeapBase(4096,
MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
-
+
mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
-
+
new(mServerCblk) surface_flinger_cblk_t;
// initialize primary screen
@@ -233,7 +233,7 @@
// Initialize OpenGL|ES
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glPixelStorei(GL_PACK_ALIGNMENT, 4);
+ glPixelStorei(GL_PACK_ALIGNMENT, 4);
glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_SCISSOR_TEST);
glShadeModel(GL_FLAT);
@@ -267,7 +267,7 @@
// start boot animation
property_set("ctl.start", "bootanim");
-
+
return NO_ERROR;
}
@@ -662,7 +662,7 @@
// Update aboveOpaqueLayers for next (lower) layer
aboveOpaqueLayers.orSelf(opaqueRegion);
-
+
// Store the visible region is screen space
layer->setVisibleRegion(visibleRegion);
layer->setCoveredRegion(coveredRegion);
@@ -781,8 +781,8 @@
glLoadIdentity();
uint32_t flags = hw.getFlags();
- if ((flags & DisplayHardware::SWAP_RECTANGLE) ||
- (flags & DisplayHardware::BUFFER_PRESERVED))
+ if ((flags & DisplayHardware::SWAP_RECTANGLE) ||
+ (flags & DisplayHardware::BUFFER_PRESERVED))
{
// we can redraw only what's dirty, but since SWAP_RECTANGLE only
// takes a rectangle, we must make sure to update that whole
@@ -1129,7 +1129,7 @@
if (android_atomic_dec(&mTransactionCount) == 1) {
signalEvent();
- // if there is a transaction with a resize, wait for it to
+ // if there is a transaction with a resize, wait for it to
// take effect before returning.
Mutex::Autolock _l(mStateLock);
while (mResizeTransationPending) {
@@ -1173,7 +1173,7 @@
return NO_ERROR;
}
-int SurfaceFlinger::setOrientation(DisplayID dpy,
+int SurfaceFlinger::setOrientation(DisplayID dpy,
int orientation, uint32_t flags)
{
if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
@@ -1206,14 +1206,17 @@
int(w), int(h));
return surfaceHandle;
}
-
+
//LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
sp<Layer> normalLayer;
switch (flags & eFXSurfaceMask) {
case eFXSurfaceNormal:
+#if HAS_PUSH_BUFFERS
if (UNLIKELY(flags & ePushBuffers)) {
layer = createPushBuffersSurface(client, d, w, h, flags);
- } else {
+ } else
+#endif
+ {
normalLayer = createNormalSurface(client, d, w, h, flags, format);
layer = normalLayer;
}
@@ -1232,7 +1235,7 @@
ssize_t token = addClientLayer(client, layer);
surfaceHandle = layer->getSurface();
- if (surfaceHandle != 0) {
+ if (surfaceHandle != 0) {
params->token = token;
params->identity = surfaceHandle->getIdentity();
params->width = w;
@@ -1316,7 +1319,7 @@
/*
* called by the window manager, when a surface should be marked for
* destruction.
- *
+ *
* The surface is removed from the current and drawing lists, but placed
* in the purgatory queue, so it's not destroyed right-away (we need
* to wait for all client's references to go away first).
@@ -1337,7 +1340,7 @@
status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
{
// called by ~ISurface() when all references are gone
-
+
class MessageDestroySurface : public MessageBase {
SurfaceFlinger* flinger;
sp<LayerBaseClient> layer;
@@ -1350,9 +1353,9 @@
layer.clear(); // clear it outside of the lock;
Mutex::Autolock _l(flinger->mStateLock);
/*
- * remove the layer from the current list -- chances are that it's
- * not in the list anyway, because it should have been removed
- * already upon request of the client (eg: window manager).
+ * remove the layer from the current list -- chances are that it's
+ * not in the list anyway, because it should have been removed
+ * already upon request of the client (eg: window manager).
* However, a buggy client could have not done that.
* Since we know we don't have any more clients, we don't need
* to use the purgatory.
@@ -1467,7 +1470,7 @@
}
const bool locked(retry >= 0);
if (!locked) {
- snprintf(buffer, SIZE,
+ snprintf(buffer, SIZE,
"SurfaceFlinger appears to be unresponsive, "
"dumping anyways (no locks held)\n");
result.append(buffer);
@@ -1742,12 +1745,15 @@
{
int32_t name = NAME_NOT_FOUND;
sp<Layer> layer(mFlinger->getLayer(sur));
- if (layer == 0) return name;
+ if (layer == 0) {
+ return name;
+ }
// if this layer already has a token, just return it
name = layer->getToken();
- if ((name >= 0) && (layer->getClient() == this))
+ if ((name >= 0) && (layer->getClient() == this)) {
return name;
+ }
name = 0;
do {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 92bed8d..2370add 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -177,7 +177,7 @@
/**
* Returns the unique device ID, for example, the IMEI for GSM and the MEID
- * for CDMA phones. Return null if device ID is not available.
+ * or ESN for CDMA phones. Return null if device ID is not available.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 8e08592..980affa 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -322,7 +322,9 @@
}
break;
}
- audioManager.setMode(mode);
+ // calling audioManager.setMode() multiple times in a short period of
+ // time seems to break the audio recorder in in-call mode
+ if (audioManager.getMode() != mode) audioManager.setMode(mode);
}
private Context getContext() {
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index 9e17eb1..f1a7107 100644
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -44,10 +44,6 @@
import android.util.Log;
import android.view.WindowManager;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.SmsMessageBase;
-import com.android.internal.telephony.SmsResponse;
-import com.android.internal.telephony.WapPushOverSms;
import com.android.internal.util.HexDump;
import java.io.ByteArrayOutputStream;
@@ -75,7 +71,7 @@
private static final int DEFAULT_SMS_MAX_COUNT = 100;
/** Default timeout for SMS sent query */
- private static final int DEFAULT_SMS_TIMOUEOUT = 6000;
+ private static final int DEFAULT_SMS_TIMEOUT = 6000;
protected static final String[] RAW_PROJECTION = new String[] {
"pdu",
@@ -83,8 +79,6 @@
"destination_port",
};
- static final int MAIL_SEND_SMS = 1;
-
static final protected int EVENT_NEW_SMS = 1;
static final protected int EVENT_SEND_SMS_COMPLETE = 2;
@@ -154,10 +148,6 @@
*/
private final int WAKE_LOCK_TIMEOUT = 5000;
- private static SmsMessage mSmsMessage;
- private static SmsMessageBase mSmsMessageBase;
- private SmsMessageBase.SubmitPduBase mSubmitPduBase;
-
protected boolean mStorageAvailable = true;
protected boolean mReportMemoryStatusPending = false;
@@ -838,7 +828,7 @@
mSTrackers.add(tracker);
sendMessageDelayed ( obtainMessage(EVENT_ALERT_TIMEOUT, d),
- DEFAULT_SMS_TIMOUEOUT);
+ DEFAULT_SMS_TIMEOUT);
}
protected String getAppNameByIntent(PendingIntent intent) {
@@ -932,7 +922,7 @@
}
/**
- * Keeps track of an SMS that has been sent to the RIL, until it it has
+ * Keeps track of an SMS that has been sent to the RIL, until it has
* successfully been sent, or we're done trying.
*
*/
@@ -973,27 +963,26 @@
}
};
- private BroadcastReceiver mResultReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_LOW)) {
- mStorageAvailable = false;
- mCm.reportSmsMemoryStatus(false, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
- } else if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_OK)) {
- mStorageAvailable = true;
- mCm.reportSmsMemoryStatus(true, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
- } else {
- // Assume the intent is one of the SMS receive intents that
- // was sent as an ordered broadcast. Check result and ACK.
- int rc = getResultCode();
- boolean success = (rc == Activity.RESULT_OK)
- || (rc == Intents.RESULT_SMS_HANDLED);
+ private BroadcastReceiver mResultReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_LOW)) {
+ mStorageAvailable = false;
+ mCm.reportSmsMemoryStatus(false, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
+ } else if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_OK)) {
+ mStorageAvailable = true;
+ mCm.reportSmsMemoryStatus(true, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
+ } else {
+ // Assume the intent is one of the SMS receive intents that
+ // was sent as an ordered broadcast. Check result and ACK.
+ int rc = getResultCode();
+ boolean success = (rc == Activity.RESULT_OK)
+ || (rc == Intents.RESULT_SMS_HANDLED);
- // For a multi-part message, this only ACKs the last part.
- // Previous parts were ACK'd as they were received.
- acknowledgeLastIncomingSms(success, rc, null);
- }
+ // For a multi-part message, this only ACKs the last part.
+ // Previous parts were ACK'd as they were received.
+ acknowledgeLastIncomingSms(success, rc, null);
}
-
- };
+ }
+ };
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 0c3c534..b39556a 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -452,9 +452,14 @@
return mMeid;
}
- //returns MEID in CDMA
+ //returns MEID or ESN in CDMA
public String getDeviceId() {
- return getMeid();
+ String id = getMeid();
+ if ((id == null) || id.matches("^0*$")) {
+ Log.d(LOG_TAG, "getDeviceId(): MEID is not initialized use ESN");
+ id = getEsn();
+ }
+ return id;
}
public String getDeviceSvn() {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 1b08aed..53d0f20 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -28,21 +28,20 @@
import android.os.AsyncResult;
import android.os.Message;
import android.os.SystemProperties;
+import android.preference.PreferenceManager;
import android.provider.Telephony;
import android.provider.Telephony.Sms.Intents;
-import android.preference.PreferenceManager;
-import android.util.Config;
-import android.util.Log;
import android.telephony.SmsManager;
import android.telephony.SmsMessage.MessageClass;
+import android.util.Config;
+import android.util.Log;
-import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.SMSDispatcher;
import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsMessageBase;
-import com.android.internal.telephony.SMSDispatcher;
import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails;
-import com.android.internal.telephony.cdma.SmsMessage;
+import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.cdma.sms.SmsEnvelope;
import com.android.internal.telephony.cdma.sms.UserData;
import com.android.internal.util.HexDump;
@@ -56,14 +55,11 @@
final class CdmaSMSDispatcher extends SMSDispatcher {
private static final String TAG = "CDMA";
- private CDMAPhone mCdmaPhone;
-
private byte[] mLastDispatchedSmsFingerprint;
private byte[] mLastAcknowledgedSmsFingerprint;
CdmaSMSDispatcher(CDMAPhone phone) {
super(phone);
- mCdmaPhone = phone;
}
/**
@@ -130,7 +126,7 @@
Log.d(TAG, "Voicemail count=" + voicemailCount);
// Store the voicemail count in preferences.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
- ((CDMAPhone) mPhone).getContext());
+ mPhone.getContext());
SharedPreferences.Editor editor = sp.edit();
editor.putInt(CDMAPhone.VM_COUNT_CDMA, voicemailCount);
editor.commit();
@@ -445,7 +441,7 @@
protected void sendSms(SmsTracker tracker) {
HashMap<String, Object> map = tracker.mData;
- byte smsc[] = (byte[]) map.get("smsc");
+ // byte smsc[] = (byte[]) map.get("smsc"); // unused for CDMA
byte pdu[] = (byte[]) map.get("pdu");
Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index aa16fa3..fe7a5cb 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -44,6 +44,13 @@
//***** Constants
+ // Max Size of the Short Code (aka Short String from TS 22.030 6.5.2)
+ static final int MAX_LENGTH_SHORT_CODE = 2;
+
+ // TS 22.030 6.5.2 Every Short String USSD command will end with #-key
+ // (known as #-String)
+ static final char END_OF_USSD_COMMAND = '#';
+
// From TS 22.030 6.5.2
static final String ACTION_ACTIVATE = "*";
static final String ACTION_DEACTIVATE = "#";
@@ -446,22 +453,69 @@
}
/**
- * Helper function for newFromDialString. Returns true if dialString appears to be a short code
- * AND conditions are correct for it to be treated as such.
+ * Helper function for newFromDialString. Returns true if dialString appears
+ * to be a short code AND conditions are correct for it to be treated as
+ * such.
*/
static private boolean isShortCode(String dialString, GSMPhone phone) {
// Refer to TS 22.030 Figure 3.5.3.2:
- // A 1 or 2 digit "short code" is treated as USSD if it is entered while on a call or
- // does not satisfy the condition (exactly 2 digits && starts with '1').
- return ((dialString != null && dialString.length() <= 2)
- && !PhoneNumberUtils.isEmergencyNumber(dialString)
- && (phone.isInCall()
- || !((dialString.length() == 2 && dialString.charAt(0) == '1')
- /* While contrary to TS 22.030, there is strong precedence
- * for treating "0" and "00" as call setup strings.
- */
- || dialString.equals("0")
- || dialString.equals("00"))));
+ if (dialString == null) {
+ return false;
+ }
+
+ // Illegal dial string characters will give a ZERO length.
+ // At this point we do not want to crash as any application with
+ // call privileges may send a non dial string.
+ // It return false as when the dialString is equal to NULL.
+ if (dialString.length() == 0) {
+ return false;
+ }
+
+ if (PhoneNumberUtils.isEmergencyNumber(dialString)) {
+ return false;
+ } else {
+ return isShortCodeUSSD(dialString, phone);
+ }
+ }
+
+ /**
+ * Helper function for isShortCode. Returns true if dialString appears to be
+ * a short code and it is a USSD structure
+ *
+ * According to the 3PGG TS 22.030 specification Figure 3.5.3.2: A 1 or 2
+ * digit "short code" is treated as USSD if it is entered while on a call or
+ * does not satisfy the condition (exactly 2 digits && starts with '1'), there
+ * are however exceptions to this rule (see below)
+ *
+ * Exception (1) to Call initiation is: If the user of the device is already in a call
+ * and enters a Short String without any #-key at the end and the length of the Short String is
+ * equal or less then the MAX_LENGTH_SHORT_CODE [constant that is equal to 2]
+ *
+ * The phone shall initiate a USSD/SS commands.
+ *
+ * Exception (2) to Call initiation is: If the user of the device enters one
+ * Digit followed by the #-key. This rule defines this String as the
+ * #-String which is a USSD/SS command.
+ *
+ * The phone shall initiate a USSD/SS command.
+ */
+ static private boolean isShortCodeUSSD(String dialString, GSMPhone phone) {
+ if (dialString != null) {
+ if (phone.isInCall()) {
+ // The maximum length of a Short Code (aka Short String) is 2
+ if (dialString.length() <= MAX_LENGTH_SHORT_CODE) {
+ return true;
+ }
+ }
+
+ // The maximum length of a Short Code (aka Short String) is 2
+ if (dialString.length() <= MAX_LENGTH_SHORT_CODE) {
+ if (dialString.charAt(dialString.length() - 1) == END_OF_USSD_COMMAND) {
+ return true;
+ }
+ }
+ }
+ return false;
}
/**
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index f09ff06..ed7066b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -27,13 +27,12 @@
import android.util.Config;
import android.util.Log;
-import com.android.internal.telephony.IccUtils;
-import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails;
-import com.android.internal.telephony.gsm.SmsMessage;
import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.IccUtils;
import com.android.internal.telephony.SMSDispatcher;
import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails;
import java.util.ArrayList;
import java.util.HashMap;
@@ -99,20 +98,20 @@
if (sms.isTypeZero()) {
// As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be
// Displayed/Stored/Notified. They should only be acknowledged.
- Log.d(TAG, "Received short message type 0, Dont display or store it. Send Ack");
+ Log.d(TAG, "Received short message type 0, Don't display or store it. Send Ack");
return Intents.RESULT_SMS_HANDLED;
}
// Special case the message waiting indicator messages
if (sms.isMWISetMessage()) {
mGsmPhone.updateMessageWaitingIndicator(true);
- handled |= sms.isMwiDontStore();
+ handled = sms.isMwiDontStore();
if (Config.LOGD) {
Log.d(TAG, "Received voice mail indicator set SMS shouldStore=" + !handled);
}
} else if (sms.isMWIClearMessage()) {
mGsmPhone.updateMessageWaitingIndicator(false);
- handled |= sms.isMwiDontStore();
+ handled = sms.isMwiDontStore();
if (Config.LOGD) {
Log.d(TAG, "Received voice mail indicator clear SMS shouldStore=" + !handled);
}
@@ -306,7 +305,7 @@
map.put("smsc", pdus.encodedScAddress);
map.put("pdu", pdus.encodedMessage);
- SmsTracker tracker = SmsTrackerFactory(map, sentIntent, deliveryIntent);
+ SmsTracker tracker = SmsTrackerFactory(map, sentIntent, deliveryIntent);
sendSms(tracker);
}
}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java
index ad05b82..f5d84eb 100644
--- a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java
@@ -85,8 +85,10 @@
protected void setState(Call.State state) {
switch (state) {
case ACTIVE:
- connectTimeReal = SystemClock.elapsedRealtime();
- connectTime = System.currentTimeMillis();
+ if (connectTime == 0) {
+ connectTimeReal = SystemClock.elapsedRealtime();
+ connectTime = System.currentTimeMillis();
+ }
break;
case DISCONNECTED:
duration = SystemClock.elapsedRealtime() - connectTimeReal;
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 81dfaeb..9a45d3a 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -107,7 +107,7 @@
}
public String getPhoneName() {
- return mProfile.getProfileName();
+ return "SIP:" + getUriString(mProfile);
}
public String getSipUri() {
@@ -225,21 +225,25 @@
}
public void conference() throws CallStateException {
- if ((foregroundCall.getState() != SipCall.State.ACTIVE)
- || (foregroundCall.getState() != SipCall.State.ACTIVE)) {
- throw new CallStateException("wrong state to merge calls: fg="
- + foregroundCall.getState() + ", bg="
- + backgroundCall.getState());
+ synchronized (SipPhone.class) {
+ if ((foregroundCall.getState() != SipCall.State.ACTIVE)
+ || (foregroundCall.getState() != SipCall.State.ACTIVE)) {
+ throw new CallStateException("wrong state to merge calls: fg="
+ + foregroundCall.getState() + ", bg="
+ + backgroundCall.getState());
+ }
+ foregroundCall.merge(backgroundCall);
}
- foregroundCall.merge(backgroundCall);
}
public void conference(Call that) throws CallStateException {
- if (!(that instanceof SipCall)) {
- throw new CallStateException("expect " + SipCall.class
- + ", cannot merge with " + that.getClass());
+ synchronized (SipPhone.class) {
+ if (!(that instanceof SipCall)) {
+ throw new CallStateException("expect " + SipCall.class
+ + ", cannot merge with " + that.getClass());
+ }
+ foregroundCall.merge((SipCall) that);
}
- foregroundCall.merge((SipCall) that);
}
public boolean canTransfer() {
@@ -251,12 +255,14 @@
}
public void clearDisconnected() {
- ringingCall.clearDisconnected();
- foregroundCall.clearDisconnected();
- backgroundCall.clearDisconnected();
+ synchronized (SipPhone.class) {
+ ringingCall.clearDisconnected();
+ foregroundCall.clearDisconnected();
+ backgroundCall.clearDisconnected();
- updatePhoneState();
- notifyPreciseCallStateChanged();
+ updatePhoneState();
+ notifyPreciseCallStateChanged();
+ }
}
public void sendDtmf(char c) {
@@ -264,7 +270,9 @@
Log.e(LOG_TAG,
"sendDtmf called with invalid character '" + c + "'");
} else if (foregroundCall.getState().isAlive()) {
- foregroundCall.sendDtmf(c);
+ synchronized (SipPhone.class) {
+ foregroundCall.sendDtmf(c);
+ }
}
}
@@ -310,7 +318,9 @@
}
public void setMute(boolean muted) {
- foregroundCall.setMute(muted);
+ synchronized (SipPhone.class) {
+ foregroundCall.setMute(muted);
+ }
}
public boolean getMute() {
@@ -413,18 +423,20 @@
@Override
public void hangup() throws CallStateException {
- Log.v(LOG_TAG, "hang up call: " + getState() + ": " + this
- + " on phone " + getPhone());
- CallStateException excp = null;
- for (Connection c : connections) {
- try {
- c.hangup();
- } catch (CallStateException e) {
- excp = e;
+ synchronized (SipPhone.class) {
+ Log.v(LOG_TAG, "hang up call: " + getState() + ": " + this
+ + " on phone " + getPhone());
+ CallStateException excp = null;
+ for (Connection c : connections) {
+ try {
+ c.hangup();
+ } catch (CallStateException e) {
+ excp = e;
+ }
}
+ if (excp != null) throw excp;
+ setState(State.DISCONNECTING);
}
- if (excp != null) throw excp;
- setState(State.DISCONNECTING);
}
void initIncomingCall(SipAudioCall sipAudioCall, boolean makeCallWait) {
@@ -457,19 +469,20 @@
}
void hold() throws CallStateException {
- AudioGroup audioGroup = getAudioGroup();
- if (audioGroup == null) return;
- audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
setState(State.HOLDING);
+ AudioGroup audioGroup = getAudioGroup();
+ if (audioGroup != null) {
+ audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
+ }
for (Connection c : connections) ((SipConnection) c).hold();
}
void unhold() throws CallStateException {
- AudioGroup audioGroup = getAudioGroup();
- if (audioGroup == null) return;
- audioGroup.setMode(AudioGroup.MODE_NORMAL);
setState(State.ACTIVE);
- for (Connection c : connections) ((SipConnection) c).unhold();
+ AudioGroup audioGroup = new AudioGroup();
+ for (Connection c : connections) {
+ ((SipConnection) c).unhold(audioGroup);
+ }
}
void setMute(boolean muted) {
@@ -486,17 +499,26 @@
}
void merge(SipCall that) throws CallStateException {
- AudioGroup myGroup = getAudioGroup();
+ AudioGroup audioGroup = getAudioGroup();
for (Connection c : that.connections) {
SipConnection conn = (SipConnection) c;
- conn.mergeTo(myGroup);
- connections.add(conn);
- conn.changeOwner(this);
+ add(conn);
+ if (conn.getState() == Call.State.HOLDING) {
+ conn.unhold(audioGroup);
+ }
}
- that.connections.clear();
that.setState(Call.State.IDLE);
}
+ private void add(SipConnection conn) {
+ SipCall call = conn.getCall();
+ if (call == this) return;
+ if (call != null) call.connections.remove(conn);
+
+ connections.add(conn);
+ conn.changeOwner(this);
+ }
+
void sendDtmf(char c) {
AudioGroup audioGroup = getAudioGroup();
if (audioGroup == null) return;
@@ -571,7 +593,6 @@
private class SipConnection extends SipConnectionBase {
private SipCall mOwner;
private SipAudioCall mSipAudioCall;
- private AudioGroup mOriginalGroup;
private Call.State mState = Call.State.IDLE;
private SipProfile mPeer;
private boolean mIncoming = false;
@@ -676,6 +697,7 @@
}
void hold() throws CallStateException {
+ setState(Call.State.HOLDING);
try {
mSipAudioCall.holdCall();
} catch (SipException e) {
@@ -683,7 +705,9 @@
}
}
- void unhold() throws CallStateException {
+ void unhold(AudioGroup audioGroup) throws CallStateException {
+ mSipAudioCall.setAudioGroup(audioGroup);
+ setState(Call.State.ACTIVE);
try {
mSipAudioCall.continueCall();
} catch (SipException e) {
@@ -691,16 +715,6 @@
}
}
- void mergeTo(AudioGroup group) throws CallStateException {
- AudioStream stream = mSipAudioCall.getAudioStream();
- if (stream == null) {
- throw new CallStateException("wrong state to merge: "
- + mSipAudioCall.getState());
- }
- if (mOriginalGroup == null) mOriginalGroup = getAudioGroup();
- stream.join(group);
- }
-
@Override
protected void setState(Call.State state) {
if (state == mState) return;
@@ -735,29 +749,36 @@
@Override
public void hangup() throws CallStateException {
- // TODO: need to pull AudioStream out of the AudioGroup in case
- // this conn was part of a conf call
- Log.v(LOG_TAG, "hangup conn: " + mPeer.getUriString() + ": "
- + ": on phone " + getPhone());
- try {
- mSipAudioCall.endCall();
- setState(Call.State.DISCONNECTING);
- setDisconnectCause(DisconnectCause.LOCAL);
- } catch (SipException e) {
- throw new CallStateException("hangup(): " + e);
+ synchronized (SipPhone.class) {
+ Log.v(LOG_TAG, "hangup conn: " + mPeer.getUriString() + ": "
+ + ": on phone " + getPhone().getPhoneName());
+ try {
+ mSipAudioCall.endCall();
+ setState(Call.State.DISCONNECTING);
+ setDisconnectCause(DisconnectCause.LOCAL);
+ } catch (SipException e) {
+ throw new CallStateException("hangup(): " + e);
+ }
}
}
@Override
public void separate() throws CallStateException {
- // TODO: what's this for SIP?
- /*
- if (!disconnected) {
- owner.separate(this);
- } else {
- throw new CallStateException ("disconnected");
+ synchronized (SipPhone.class) {
+ SipCall call = (SipCall) SipPhone.this.getBackgroundCall();
+ if (call.getState() != Call.State.IDLE) {
+ throw new CallStateException(
+ "cannot put conn back to a call in non-idle state: "
+ + call.getState());
+ }
+ Log.v(LOG_TAG, "separate conn: " + mPeer.getUriString()
+ + " from " + mOwner + " back to " + call);
+
+ AudioGroup audioGroup = call.getAudioGroup(); // may be null
+ call.add(this);
+ mSipAudioCall.setAudioGroup(audioGroup);
+ call.hold();
}
- */
}
}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
index 721b8af..1d33be9 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
@@ -174,10 +174,6 @@
return state;
}
- public String getPhoneName() {
- return "SIP";
- }
-
public int getPhoneType() {
// FIXME: add SIP phone type
return Phone.PHONE_TYPE_GSM;
diff --git a/tests/DumpRenderTree/AndroidManifest.xml b/tests/DumpRenderTree/AndroidManifest.xml
index 03b7e26..c151251 100644
--- a/tests/DumpRenderTree/AndroidManifest.xml
+++ b/tests/DumpRenderTree/AndroidManifest.xml
@@ -18,15 +18,18 @@
<application android:name="HTMLHostApp">
<uses-library android:name="android.test.runner" />
<activity android:name="Menu" android:label="Dump Render Tree"
- android:screenOrientation="portrait">
+ android:screenOrientation="portrait"
+ android:theme="@android:style/Theme.Light">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.TEST" />
</intent-filter>
</activity>
<activity android:name="TestShellActivity" android:launchMode="singleTop"
- android:screenOrientation="portrait"/>
- <activity android:name="ReliabilityTestActivity" android:screenOrientation="portrait"/>
+ android:screenOrientation="portrait"
+ android:theme="@android:style/Theme.Light"/>
+ <activity android:name="ReliabilityTestActivity" android:screenOrientation="portrait"
+ android:theme="@android:style/Theme.Light"/>
</application>
<instrumentation android:name=".LayoutTestsAutoRunner"
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 9f580a3..4cff3de 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -95,6 +95,7 @@
ignoreResultList.add("http/tests/appcache/fallback.html"); // http://b/issue?id=2713004
ignoreResultList.add("http/tests/appcache/foreign-iframe-main.html"); // flaky - skips states
ignoreResultList.add("http/tests/appcache/manifest-with-empty-file.html"); // flaky
+ ignoreResultList.add("http/tests/appcache/origin-quota.html"); // needs clearAllApplicationCaches(), see http://b/issue?id=2944196
ignoreResultList.add("storage/database-lock-after-reload.html"); // Succeeds but DumpRenderTree does not read result correctly
ignoreResultList.add("storage/hash-change-with-xhr.html"); // Succeeds but DumpRenderTree does not read result correctly
ignoreResultList.add("storage/open-database-creation-callback-isolated-world.html"); // Requires layoutTestController.evaluateScriptInIsolatedWorld()
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index c40af80..abccf9b 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -338,6 +338,7 @@
SMALL_SCREEN_ATTR = 0x01010284,
NORMAL_SCREEN_ATTR = 0x01010285,
LARGE_SCREEN_ATTR = 0x01010286,
+ XLARGE_SCREEN_ATTR = 0x010102bf,
REQUIRED_ATTR = 0x0101028e,
};
@@ -572,6 +573,7 @@
int smallScreen = 1;
int normalScreen = 1;
int largeScreen = 1;
+ int xlargeScreen = 1;
String8 pkg;
String8 activityName;
String8 activityLabel;
@@ -754,6 +756,8 @@
NORMAL_SCREEN_ATTR, NULL, 1);
largeScreen = getIntegerAttribute(tree,
LARGE_SCREEN_ATTR, NULL, 1);
+ xlargeScreen = getIntegerAttribute(tree,
+ XLARGE_SCREEN_ATTR, NULL, 1);
} else if (tag == "uses-feature") {
String8 name = getAttribute(tree, NAME_ATTR, &error);
@@ -1082,10 +1086,15 @@
if (largeScreen > 0) {
largeScreen = targetSdk >= 4 ? -1 : 0;
}
+ if (xlargeScreen > 0) {
+ // Introduced in Honeycomb.
+ xlargeScreen = targetSdk >= 10 ? -1 : 0;
+ }
printf("supports-screens:");
if (smallScreen != 0) printf(" 'small'");
if (normalScreen != 0) printf(" 'normal'");
if (largeScreen != 0) printf(" 'large'");
+ if (xlargeScreen != 0) printf(" 'xlarge'");
printf("\n");
printf("locales:");
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index f4be839..3cdd114 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -244,7 +244,8 @@
* Also, the {@code AudioStream} may change its group during a call (e.g.,
* after the call is held/un-held). Finally, the {@code AudioGroup} object
* returned by this method is undefined after the call ends or the
- * {@link #close} method is called.
+ * {@link #close} method is called. If a group object is set by
+ * {@link #setAudioGroup(AudioGroup)}, then this method returns that object.
*
* @return the {@link AudioGroup} object or null if the RTP stream has not
* yet been set up
@@ -253,6 +254,15 @@
AudioGroup getAudioGroup();
/**
+ * Sets the {@link AudioGroup} object which the {@link AudioStream} object
+ * joins. If {@code audioGroup} is null, then the {@code AudioGroup} object
+ * will be dynamically created when needed.
+ *
+ * @see #getAudioStream
+ */
+ void setAudioGroup(AudioGroup audioGroup);
+
+ /**
* Checks if the call is established.
*
* @return true if the call is established
diff --git a/voip/java/android/net/sip/SipAudioCallImpl.java b/voip/java/android/net/sip/SipAudioCallImpl.java
index 7161309..b8ac6d7 100644
--- a/voip/java/android/net/sip/SipAudioCallImpl.java
+++ b/voip/java/android/net/sip/SipAudioCallImpl.java
@@ -70,7 +70,8 @@
private ISipSession mSipSession;
private SdpSessionDescription mPeerSd;
- private AudioStream mRtpSession;
+ private AudioStream mAudioStream;
+ private AudioGroup mAudioGroup;
private SdpSessionDescription.AudioCodec mCodec;
private long mSessionId = -1L; // SDP session ID
private boolean mInCall = false;
@@ -505,11 +506,19 @@
}
public synchronized AudioStream getAudioStream() {
- return mRtpSession;
+ return mAudioStream;
}
public synchronized AudioGroup getAudioGroup() {
- return ((mRtpSession == null) ? null : mRtpSession.getAudioGroup());
+ if (mAudioGroup != null) return mAudioGroup;
+ return ((mAudioStream == null) ? null : mAudioStream.getAudioGroup());
+ }
+
+ public synchronized void setAudioGroup(AudioGroup group) {
+ if ((mAudioStream != null) && (mAudioStream.getAudioGroup() != null)) {
+ mAudioStream.join(group);
+ }
+ mAudioGroup = group;
}
private SdpSessionDescription.AudioCodec getCodec(SdpSessionDescription sd) {
@@ -561,7 +570,7 @@
// TODO: get sample rate from sdp
mCodec = getCodec(peerSd);
- AudioStream audioStream = mRtpSession;
+ AudioStream audioStream = mAudioStream;
audioStream.associate(InetAddress.getByName(peerMediaAddress),
peerMediaPort);
audioStream.setCodec(convert(mCodec), mCodec.payloadType);
@@ -580,7 +589,7 @@
Log.d(TAG, " not sending");
audioStream.setMode(RtpStream.MODE_RECEIVE_ONLY);
}
- } else {
+
/* The recorder volume will be very low if the device is in
* IN_CALL mode. Therefore, we have to set the mode to NORMAL
* in order to have the normal microphone level.
@@ -590,14 +599,22 @@
.setMode(AudioManager.MODE_NORMAL);
}
- AudioGroup audioGroup = new AudioGroup();
- audioStream.join(audioGroup);
+ // AudioGroup logic:
+ AudioGroup audioGroup = getAudioGroup();
if (mHold) {
- audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
- } else if (mMuted) {
- audioGroup.setMode(AudioGroup.MODE_MUTED);
+ if (audioGroup != null) {
+ audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
+ }
+ // don't create an AudioGroup here; doing so will fail if
+ // there's another AudioGroup out there that's active
} else {
- audioGroup.setMode(AudioGroup.MODE_NORMAL);
+ if (audioGroup == null) audioGroup = new AudioGroup();
+ audioStream.join(audioGroup);
+ if (mMuted) {
+ audioGroup.setMode(AudioGroup.MODE_MUTED);
+ } else {
+ audioGroup.setMode(AudioGroup.MODE_NORMAL);
+ }
}
} catch (Exception e) {
Log.e(TAG, "call()", e);
@@ -606,20 +623,20 @@
private void stopCall(boolean releaseSocket) {
Log.d(TAG, "stop audiocall");
- if (mRtpSession != null) {
- mRtpSession.join(null);
+ if (mAudioStream != null) {
+ mAudioStream.join(null);
if (releaseSocket) {
- mRtpSession.release();
- mRtpSession = null;
+ mAudioStream.release();
+ mAudioStream = null;
}
}
}
private int getLocalMediaPort() {
- if (mRtpSession != null) return mRtpSession.getLocalPort();
+ if (mAudioStream != null) return mAudioStream.getLocalPort();
try {
- AudioStream s = mRtpSession =
+ AudioStream s = mAudioStream =
new AudioStream(InetAddress.getByName(getLocalIp()));
return s.getLocalPort();
} catch (IOException e) {
diff --git a/voip/jni/rtp/Android.mk b/voip/jni/rtp/Android.mk
index a364355..3bd85aa 100644
--- a/voip/jni/rtp/Android.mk
+++ b/voip/jni/rtp/Android.mk
@@ -32,10 +32,11 @@
libutils \
libmedia
-LOCAL_STATIC_LIBRARIES :=
+LOCAL_STATIC_LIBRARIES := libspeex
LOCAL_C_INCLUDES += \
- $(JNI_H_INCLUDE)
+ $(JNI_H_INCLUDE) \
+ external/speex/include
LOCAL_CFLAGS += -fvisibility=hidden
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 08a8d1c..b5a4e22 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -40,6 +40,8 @@
#include <media/AudioTrack.h>
#include <media/mediarecorder.h>
+#include <speex/speex_echo.h>
+
#include "jni.h"
#include "JNIHelp.h"
@@ -445,6 +447,8 @@
int mDeviceSocket;
AudioTrack mTrack;
AudioRecord mRecord;
+
+ SpeexEchoState *mEchoState;
bool networkLoop();
bool deviceLoop();
@@ -506,6 +510,7 @@
mEventQueue = -1;
mDtmfEvent = -1;
mDeviceSocket = -1;
+ mEchoState = NULL;
mNetworkThread = new NetworkThread(this);
mDeviceThread = new DeviceThread(this);
}
@@ -518,6 +523,9 @@
mRecord.stop();
close(mEventQueue);
close(mDeviceSocket);
+ if (mEchoState) {
+ speex_echo_state_destroy(mEchoState);
+ }
while (mChain) {
AudioStream *next = mChain->mNext;
delete mChain;
@@ -548,10 +556,11 @@
}
LOGD("reported frame count: output %d, input %d", output, input);
- output = (output + sampleCount - 1) / sampleCount * sampleCount;
- input = (input + sampleCount - 1) / sampleCount * sampleCount;
- if (input < output * 2) {
- input = output * 2;
+ if (output < sampleCount * 2) {
+ output = sampleCount * 2;
+ }
+ if (input < sampleCount * 2) {
+ input = sampleCount * 2;
}
LOGD("adjusted frame count: output %d, input %d", output, input);
@@ -565,7 +574,8 @@
}
LOGD("latency: output %d, input %d", mTrack.latency(), mRecord.latency());
- // TODO: initialize echo canceler here.
+ // Initialize echo canceller.
+ mEchoState = speex_echo_state_init(sampleCount, sampleRate);
// Create device socket.
int pair[2];
@@ -587,7 +597,7 @@
// Give device socket a reasonable timeout and buffer size.
timeval tv;
tv.tv_sec = 0;
- tv.tv_usec = 1000 * sampleCount / sampleRate * 500;
+ tv.tv_usec = 1000 * sampleCount / sampleRate * 1000;
if (setsockopt(pair[0], SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) ||
setsockopt(pair[0], SOL_SOCKET, SO_RCVBUF, &output, sizeof(output)) ||
setsockopt(pair[1], SOL_SOCKET, SO_SNDBUF, &output, sizeof(output))) {
@@ -632,6 +642,7 @@
if (mode == MUTED) {
mRecord.stop();
} else {
+ speex_echo_state_reset(mEchoState);
mRecord.start();
}
@@ -764,38 +775,63 @@
if (recv(mDeviceSocket, output, sizeof(output), 0) <= 0) {
memset(output, 0, sizeof(output));
}
- if (mTrack.write(output, sizeof(output)) != (int)sizeof(output)) {
- LOGE("cannot write to AudioTrack");
+
+ int16_t input[mSampleCount];
+ int toWrite = mSampleCount;
+ int toRead = (mMode == MUTED) ? 0 : mSampleCount;
+ int chances = 100;
+
+ while (--chances > 0 && (toWrite > 0 || toRead > 0)) {
+ if (toWrite > 0) {
+ AudioTrack::Buffer buffer;
+ buffer.frameCount = toWrite;
+
+ status_t status = mTrack.obtainBuffer(&buffer, 1);
+ if (status == NO_ERROR) {
+ memcpy(buffer.i8, &output[mSampleCount - toWrite], buffer.size);
+ toWrite -= buffer.frameCount;
+ mTrack.releaseBuffer(&buffer);
+ } else if (status != TIMED_OUT && status != WOULD_BLOCK) {
+ LOGE("cannot write to AudioTrack");
+ return false;
+ }
+ }
+
+ if (toRead > 0) {
+ AudioRecord::Buffer buffer;
+ buffer.frameCount = mRecord.frameCount();
+
+ status_t status = mRecord.obtainBuffer(&buffer, 1);
+ if (status == NO_ERROR) {
+ int count = ((int)buffer.frameCount < toRead) ?
+ buffer.frameCount : toRead;
+ memcpy(&input[mSampleCount - toRead], buffer.i8, count * 2);
+ toRead -= count;
+ if (buffer.frameCount < mRecord.frameCount()) {
+ buffer.frameCount = count;
+ }
+ mRecord.releaseBuffer(&buffer);
+ } else if (status != TIMED_OUT && status != WOULD_BLOCK) {
+ LOGE("cannot read from AudioRecord");
+ return false;
+ }
+ }
+ }
+
+ if (!chances) {
+ LOGE("device loop timeout");
return false;
}
if (mMode != MUTED) {
- uint32_t frameCount = mRecord.frameCount();
- AudioRecord::Buffer input;
- input.frameCount = frameCount;
-
- if (mRecord.obtainBuffer(&input, -1) != NO_ERROR) {
- LOGE("cannot read from AudioRecord");
- return false;
- }
-
- if (input.frameCount < (uint32_t)mSampleCount) {
- input.frameCount = 0;
+ if (mMode == NORMAL) {
+ send(mDeviceSocket, input, sizeof(input), MSG_DONTWAIT);
} else {
- if (mMode == NORMAL) {
- send(mDeviceSocket, input.i8, sizeof(output), MSG_DONTWAIT);
- } else {
- // TODO: Echo canceller runs here.
- send(mDeviceSocket, input.i8, sizeof(output), MSG_DONTWAIT);
- }
- if (input.frameCount < frameCount) {
- input.frameCount = mSampleCount;
- }
+ int16_t result[mSampleCount];
+ speex_echo_cancellation(mEchoState, input, output, result);
+ send(mDeviceSocket, result, sizeof(result), MSG_DONTWAIT);
}
-
- mRecord.releaseBuffer(&input);
}
-
return true;
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 01bc919..559be85 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -432,6 +432,38 @@
return 0;
}
+ /**
+ * Returns a copy of this WifiConfiguration.
+ *
+ * @return a copy of this WifiConfiguration.
+ * @hide
+ */
+ public WifiConfiguration clone() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.networkId = networkId;
+ config.status = status;
+ config.SSID = SSID;
+ config.BSSID = BSSID;
+ config.preSharedKey = preSharedKey;
+
+ for (int i = 0; i < wepKeys.length; i++)
+ config.wepKeys[i] = wepKeys[i];
+
+ config.wepTxKeyIndex = wepTxKeyIndex;
+ config.priority = priority;
+ config.hiddenSSID = hiddenSSID;
+ config.allowedKeyManagement = (BitSet) allowedKeyManagement.clone();
+ config.allowedProtocols = (BitSet) allowedProtocols.clone();
+ config.allowedAuthAlgorithms = (BitSet) allowedAuthAlgorithms.clone();
+ config.allowedPairwiseCiphers = (BitSet) allowedPairwiseCiphers.clone();
+ config.allowedGroupCiphers = (BitSet) allowedGroupCiphers.clone();
+
+ for (int i = 0; i < enterpriseFields.length; i++) {
+ config.enterpriseFields[i].setValue(enterpriseFields[i].value());
+ }
+ return config;
+ }
+
/** Implement the Parcelable interface {@hide} */
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(networkId);
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 19c4eb0..5734953 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -79,6 +79,7 @@
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.BitSet;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -126,6 +127,7 @@
private int mReconnectCount = 0;
private boolean mIsScanMode = false;
private boolean mConfigChanged = false;
+ private List<WifiConfiguration> mConfiguredNetworks = new ArrayList<WifiConfiguration>();
/**
* Instance of the bluetooth headset helper. This needs to be created
@@ -232,12 +234,8 @@
private static final int CMD_BLACKLIST_NETWORK = 56;
/* Clear the blacklist network list */
private static final int CMD_CLEAR_BLACKLIST = 57;
- /* Get the configured networks */
- private static final int CMD_GET_NETWORK_CONFIG = 58;
/* Save configuration */
- private static final int CMD_SAVE_CONFIG = 59;
- /* Connection status */
- private static final int CMD_CONNECTION_STATUS = 60;
+ private static final int CMD_SAVE_CONFIG = 58;
/* Supplicant commands after driver start*/
/* Initiate a scan */
@@ -379,10 +377,6 @@
/* Soft Ap is running */
private HierarchicalState mSoftApStartedState = new SoftApStartedState();
- /* Argument for Message object to indicate a synchronous call */
- private static final int SYNCHRONOUS_CALL = 1;
- private static final int ASYNCHRONOUS_CALL = 0;
-
/**
* One of {@link WifiManager#WIFI_STATE_DISABLED},
@@ -488,7 +482,7 @@
/**
* TODO: doc
*/
- public boolean pingSupplicant() {
+ public boolean syncPingSupplicant() {
return sendSyncMessage(CMD_PING_SUPPLICANT).boolValue;
}
@@ -535,14 +529,14 @@
/**
* TODO: doc
*/
- public int getWifiState() {
+ public int syncGetWifiState() {
return mWifiState.get();
}
/**
* TODO: doc
*/
- public String getWifiStateByName() {
+ public String syncGetWifiStateByName() {
switch (mWifiState.get()) {
case WIFI_STATE_DISABLING:
return "disabling";
@@ -562,14 +556,14 @@
/**
* TODO: doc
*/
- public int getWifiApState() {
+ public int syncGetWifiApState() {
return mWifiApState.get();
}
/**
* TODO: doc
*/
- public String getWifiApStateByName() {
+ public String syncGetWifiApStateByName() {
switch (mWifiApState.get()) {
case WIFI_AP_STATE_DISABLING:
return "disabling";
@@ -591,11 +585,11 @@
* @return a {@link WifiInfo} object containing information about the current connection
*
*/
- public WifiInfo requestConnectionInfo() {
+ public WifiInfo syncRequestConnectionInfo() {
return mWifiInfo;
}
- public DhcpInfo getDhcpInfo() {
+ public DhcpInfo syncGetDhcpInfo() {
return mDhcpInfo;
}
@@ -635,7 +629,7 @@
/**
* TODO: doc
*/
- public List<ScanResult> getScanResultsList() {
+ public List<ScanResult> syncGetScanResultsList() {
return mScanResults;
}
@@ -665,12 +659,19 @@
*
* @return network id of the new network
*/
- public int addOrUpdateNetwork(WifiConfiguration config) {
+ public int syncAddOrUpdateNetwork(WifiConfiguration config) {
return sendSyncMessage(CMD_ADD_OR_UPDATE_NETWORK, config).intValue;
}
- public List<WifiConfiguration> getConfiguredNetworks() {
- return sendSyncMessage(CMD_GET_NETWORK_CONFIG).configList;
+ public List<WifiConfiguration> syncGetConfiguredNetworks() {
+ List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
+ synchronized (mConfiguredNetworks) {
+ Iterator<WifiConfiguration> iterator = mConfiguredNetworks.iterator();
+ while(iterator.hasNext()) {
+ networks.add(iterator.next().clone());
+ }
+ }
+ return networks;
}
/**
@@ -678,7 +679,7 @@
*
* @param networkId id of the network to be removed
*/
- public boolean removeNetwork(int networkId) {
+ public boolean syncRemoveNetwork(int networkId) {
return sendSyncMessage(obtainMessage(CMD_REMOVE_NETWORK, networkId, 0)).boolValue;
}
@@ -697,7 +698,7 @@
* @param disableOthers true, if all other networks have to be disabled
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
- public boolean enableNetwork(int netId, boolean disableOthers) {
+ public boolean syncEnableNetwork(int netId, boolean disableOthers) {
return sendSyncMessage(CMD_ENABLE_NETWORK,
new EnableNetParams(netId, disableOthers)).boolValue;
}
@@ -708,7 +709,7 @@
* @param netId network id of the network
* @return {@code true} if the operation succeeds, {@code false} otherwise
*/
- public boolean disableNetwork(int netId) {
+ public boolean syncDisableNetwork(int netId) {
return sendSyncMessage(obtainMessage(CMD_DISABLE_NETWORK, netId, 0)).boolValue;
}
@@ -746,23 +747,6 @@
sendMessage(obtainMessage(CMD_FORGET_NETWORK, netId, 0));
}
- /**
- * Get detailed status of the connection
- *
- * @return Example status result
- * bssid=aa:bb:cc:dd:ee:ff
- * ssid=TestNet
- * id=3
- * pairwise_cipher=NONE
- * group_cipher=NONE
- * key_mgmt=NONE
- * wpa_state=COMPLETED
- * ip_address=X.X.X.X
- */
- public String status() {
- return sendSyncMessage(CMD_CONNECTION_STATUS).stringValue;
- }
-
public void enableRssiPolling(boolean enabled) {
sendMessage(obtainMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0));
}
@@ -771,7 +755,7 @@
*
* @return RSSI value, -1 on failure
*/
- public int getRssi() {
+ public int syncGetRssi() {
return sendSyncMessage(CMD_GET_RSSI).intValue;
}
@@ -780,7 +764,7 @@
*
* @return RSSI value, -1 on failure
*/
- public int getRssiApprox() {
+ public int syncGetRssiApprox() {
return sendSyncMessage(CMD_GET_RSSI_APPROX).intValue;
}
@@ -789,7 +773,7 @@
*
* @return link speed, -1 on failure
*/
- public int getLinkSpeed() {
+ public int syncGetLinkSpeed() {
return sendSyncMessage(CMD_GET_LINK_SPEED).intValue;
}
@@ -798,7 +782,7 @@
*
* @return MAC address, null on failure
*/
- public String getMacAddress() {
+ public String syncGetMacAddress() {
return sendSyncMessage(CMD_GET_MAC_ADDR).stringValue;
}
@@ -895,7 +879,7 @@
*
* TODO: deprecate this
*/
- public boolean saveConfig() {
+ public boolean syncSaveConfig() {
return sendSyncMessage(CMD_SAVE_CONFIG).boolValue;
}
@@ -915,7 +899,6 @@
int intValue;
String stringValue;
Object objValue;
- List<WifiConfiguration> configList;
}
class SyncParams {
@@ -931,12 +914,10 @@
}
/**
- * message.arg2 is reserved to indicate synchronized
* message.obj is used to store SyncParams
*/
private SyncReturn syncedSend(Message msg) {
SyncParams syncParams = (SyncParams) msg.obj;
- msg.arg2 = SYNCHRONOUS_CALL;
synchronized(syncParams) {
if (DBG) Log.d(TAG, "syncedSend " + msg);
sendMessage(msg);
@@ -995,7 +976,7 @@
mWifiState.set(wifiState);
- if (DBG) Log.d(TAG, "setWifiState: " + getWifiStateByName());
+ if (DBG) Log.d(TAG, "setWifiState: " + syncGetWifiStateByName());
final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -1020,7 +1001,7 @@
// Update state
mWifiApState.set(wifiApState);
- if (DBG) Log.d(TAG, "setWifiApState: " + getWifiApStateByName());
+ if (DBG) Log.d(TAG, "setWifiApState: " + syncGetWifiApStateByName());
final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -1395,6 +1376,7 @@
}
private void sendConfigChangeBroadcast() {
+ if (!ActivityManagerNative.isSystemReady()) return;
Intent intent = new Intent(WifiManager.CONFIG_CHANGED_ACTION);
intent.putExtra(WifiManager.EXTRA_NETWORK_PROPERTIES, mNetworkProperties);
mContext.sendBroadcast(intent);
@@ -1413,7 +1395,9 @@
mContext.sendStickyBroadcast(intent);
}
- private void sendSupplicantConfigChangedBroadcast() {
+ private void updateConfigAndSendChangeBroadcast() {
+ updateConfiguredNetworks();
+ if (!ActivityManagerNative.isSystemReady()) return;
Intent intent = new Intent(WifiManager.SUPPLICANT_CONFIG_CHANGED_ACTION);
mContext.sendBroadcast(intent);
}
@@ -1487,14 +1471,13 @@
private void enableAllNetworks() {
if (mEnableAllNetworks) {
mEnableAllNetworks = false;
- List<WifiConfiguration> configList = getConfiguredNetworksNative();
- for (WifiConfiguration config : configList) {
+ for (WifiConfiguration config : mConfiguredNetworks) {
if(config != null && config.status == Status.DISABLED) {
WifiNative.enableNetworkCommand(config.networkId, false);
}
}
WifiNative.saveConfigCommand();
- sendSupplicantConfigChangedBroadcast();
+ updateConfigAndSendChangeBroadcast();
}
}
@@ -1689,44 +1672,47 @@
return -1;
}
- private List<WifiConfiguration> getConfiguredNetworksNative() {
+ private void updateConfiguredNetworks() {
String listStr = WifiNative.listNetworksCommand();
mLastPriority = 0;
- List<WifiConfiguration> networks =
- new ArrayList<WifiConfiguration>();
- if (listStr == null)
- return networks;
- String[] lines = listStr.split("\n");
- // Skip the first line, which is a header
- for (int i = 1; i < lines.length; i++) {
- String[] result = lines[i].split("\t");
- // network-id | ssid | bssid | flags
- WifiConfiguration config = new WifiConfiguration();
- try {
- config.networkId = Integer.parseInt(result[0]);
- } catch(NumberFormatException e) {
- continue;
- }
- if (result.length > 3) {
- if (result[3].indexOf("[CURRENT]") != -1)
- config.status = WifiConfiguration.Status.CURRENT;
- else if (result[3].indexOf("[DISABLED]") != -1)
- config.status = WifiConfiguration.Status.DISABLED;
- else
+ synchronized (mConfiguredNetworks) {
+ mConfiguredNetworks.clear();
+
+ if (listStr == null)
+ return;
+
+ String[] lines = listStr.split("\n");
+ // Skip the first line, which is a header
+ for (int i = 1; i < lines.length; i++) {
+ String[] result = lines[i].split("\t");
+ // network-id | ssid | bssid | flags
+ WifiConfiguration config = new WifiConfiguration();
+ try {
+ config.networkId = Integer.parseInt(result[0]);
+ } catch(NumberFormatException e) {
+ continue;
+ }
+ if (result.length > 3) {
+ if (result[3].indexOf("[CURRENT]") != -1)
+ config.status = WifiConfiguration.Status.CURRENT;
+ else if (result[3].indexOf("[DISABLED]") != -1)
+ config.status = WifiConfiguration.Status.DISABLED;
+ else
+ config.status = WifiConfiguration.Status.ENABLED;
+ } else {
config.status = WifiConfiguration.Status.ENABLED;
- } else {
- config.status = WifiConfiguration.Status.ENABLED;
+ }
+ readNetworkVariables(config);
+ if (config.priority > mLastPriority) {
+ mLastPriority = config.priority;
+ }
+ mConfiguredNetworks.add(config);
}
- readNetworkVariables(config);
- if (config.priority > mLastPriority) {
- mLastPriority = config.priority;
- }
- networks.add(config);
}
- return networks;
}
+
/**
* Read the variables from the supplicant daemon that are needed to
* fill in the WifiConfiguration object.
@@ -2082,16 +2068,11 @@
case CMD_GET_LINK_SPEED:
case CMD_GET_MAC_ADDR:
case CMD_SAVE_CONFIG:
- case CMD_CONNECTION_STATUS:
- case CMD_GET_NETWORK_CONFIG:
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = false;
- syncParams.mSyncReturn.intValue = -1;
- syncParams.mSyncReturn.stringValue = null;
- syncParams.mSyncReturn.configList = null;
- notifyOnMsgObject(message);
- }
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = false;
+ syncParams.mSyncReturn.intValue = -1;
+ syncParams.mSyncReturn.stringValue = null;
+ notifyOnMsgObject(message);
break;
case CMD_ENABLE_RSSI_POLL:
mEnableRssiPolling = (message.arg1 == 1);
@@ -2423,6 +2404,8 @@
mWifiInfo.setMacAddress(WifiNative.getMacAddressCommand());
+ updateConfigAndSendChangeBroadcast();
+
//TODO: initialize and fix multicast filtering
//mWM.initializeMulticastFiltering();
@@ -2521,48 +2504,33 @@
syncParams = (SyncParams) message.obj;
config = (WifiConfiguration) syncParams.mParameter;
syncParams.mSyncReturn.intValue = addOrUpdateNetworkNative(config);
+ updateConfigAndSendChangeBroadcast();
notifyOnMsgObject(message);
- sendSupplicantConfigChangedBroadcast();
break;
case CMD_REMOVE_NETWORK:
EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.removeNetworkCommand(
- message.arg1);
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.removeNetworkCommand(message.arg1);
- }
- sendSupplicantConfigChangedBroadcast();
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.removeNetworkCommand(
+ message.arg1);
+ updateConfigAndSendChangeBroadcast();
+ notifyOnMsgObject(message);
break;
case CMD_ENABLE_NETWORK:
EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- EnableNetParams enableNetParams = (EnableNetParams) syncParams.mParameter;
- syncParams.mSyncReturn.boolValue = WifiNative.enableNetworkCommand(
- enableNetParams.netId, enableNetParams.disableOthers);
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.enableNetworkCommand(message.arg1, message.arg2 == 1);
- }
- sendSupplicantConfigChangedBroadcast();
+ syncParams = (SyncParams) message.obj;
+ EnableNetParams enableNetParams = (EnableNetParams) syncParams.mParameter;
+ syncParams.mSyncReturn.boolValue = WifiNative.enableNetworkCommand(
+ enableNetParams.netId, enableNetParams.disableOthers);
+ updateConfigAndSendChangeBroadcast();
+ notifyOnMsgObject(message);
break;
case CMD_DISABLE_NETWORK:
EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.disableNetworkCommand(
- message.arg1);
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.disableNetworkCommand(message.arg1);
- }
- sendSupplicantConfigChangedBroadcast();
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.disableNetworkCommand(
+ message.arg1);
+ updateConfigAndSendChangeBroadcast();
+ notifyOnMsgObject(message);
break;
case CMD_BLACKLIST_NETWORK:
EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
@@ -2571,20 +2539,10 @@
case CMD_CLEAR_BLACKLIST:
WifiNative.clearBlacklistCommand();
break;
- case CMD_GET_NETWORK_CONFIG:
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.configList = getConfiguredNetworksNative();
- notifyOnMsgObject(message);
- break;
case CMD_SAVE_CONFIG:
- if (message.arg2 == SYNCHRONOUS_CALL) {
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.boolValue = WifiNative.saveConfigCommand();
- notifyOnMsgObject(message);
- } else {
- /* asynchronous handling */
- WifiNative.saveConfigCommand();
- }
+ syncParams = (SyncParams) message.obj;
+ syncParams.mSyncReturn.boolValue = WifiNative.saveConfigCommand();
+ notifyOnMsgObject(message);
// Inform the backup manager about a data change
IBackupManager ibm = IBackupManager.Stub.asInterface(
ServiceManager.getService(Context.BACKUP_SERVICE));
@@ -2596,11 +2554,6 @@
}
}
break;
- case CMD_CONNECTION_STATUS:
- syncParams = (SyncParams) message.obj;
- syncParams.mSyncReturn.stringValue = WifiNative.statusCommand();
- notifyOnMsgObject(message);
- break;
case CMD_GET_MAC_ADDR:
syncParams = (SyncParams) message.obj;
syncParams.mSyncReturn.stringValue = WifiNative.getMacAddressCommand();
@@ -2623,12 +2576,12 @@
WifiNative.enableNetworkCommand(netId, false);
}
WifiNative.saveConfigCommand();
- sendSupplicantConfigChangedBroadcast();
+ updateConfigAndSendChangeBroadcast();
break;
case CMD_FORGET_NETWORK:
WifiNative.removeNetworkCommand(message.arg1);
WifiNative.saveConfigCommand();
- sendSupplicantConfigChangedBroadcast();
+ updateConfigAndSendChangeBroadcast();
break;
default:
return NOT_HANDLED;
@@ -2905,8 +2858,7 @@
}
// Reset the priority of each network at start or if it goes too high.
if (mLastPriority == -1 || mLastPriority > 1000000) {
- List<WifiConfiguration> configList = getConfiguredNetworksNative();
- for (WifiConfiguration conf : configList) {
+ for (WifiConfiguration conf : mConfiguredNetworks) {
if (conf.networkId != -1) {
conf.priority = 0;
addOrUpdateNetworkNative(conf);
@@ -2927,10 +2879,11 @@
WifiNative.enableNetworkCommand(netId, true);
WifiNative.reconnectCommand();
mEnableAllNetworks = true;
- /* Dont send a supplicant config change broadcast here
- * as it is better to not expose the temporary disabling
- * of all networks
+ /* update the configured networks but not send a
+ * broadcast to avoid a fetch from settings
+ * during this temporary disabling of networks
*/
+ updateConfiguredNetworks();
break;
case SCAN_RESULTS_EVENT:
/* Set the scan setting back to "connect" mode */
@@ -3090,7 +3043,7 @@
Log.e(TAG, "Failed " +
mReconnectCount + " times, Disabling " + mLastNetworkId);
WifiNative.disableNetworkCommand(mLastNetworkId);
- sendSupplicantConfigChangedBroadcast();
+ updateConfigAndSendChangeBroadcast();
}
/* DHCP times out after about 30 seconds, we do a
@@ -3503,7 +3456,7 @@
WifiNative.disableNetworkCommand(mWifiInfo.getNetworkId());
mPasswordKeyMayBeIncorrect = false;
sendSupplicantStateChangedBroadcast(stateChangeResult, true);
- sendSupplicantConfigChangedBroadcast();
+ updateConfigAndSendChangeBroadcast();
}
else {
sendSupplicantStateChangedBroadcast(stateChangeResult, false);
@@ -3563,7 +3516,7 @@
}
if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) {
WifiNative.disableNetworkCommand(stateChangeResult.networkId);
- sendSupplicantConfigChangedBroadcast();
+ updateConfigAndSendChangeBroadcast();
mLoopDetectCount = 0;
}