diff options
404 files changed, 13565 insertions, 2229 deletions
diff --git a/Android.mk b/Android.mk index a73767ba00e2..7c848c607708 100644 --- a/Android.mk +++ b/Android.mk @@ -123,10 +123,6 @@ LOCAL_SRC_FILES += \ 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 @@ sample_dir := development/samples # (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 f73e4d5d555c..a9f4d195faa1 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -76,6 +76,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhwui_interm $(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 d935c387b1cc..cbbf3d1fe8bf 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 68415f009225..a49ca8fca7f6 100644 --- a/core/java/android/animation/Animatable.java +++ b/core/java/android/animation/Animatable.java @@ -22,7 +22,7 @@ import java.util.ArrayList; * 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 @@ public abstract class Animatable { } } + @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 951d104ad3fe..eca5f0d29601 100755 --- a/core/java/android/animation/Animator.java +++ b/core/java/android/animation/Animator.java @@ -19,6 +19,7 @@ package android.animation; import android.content.Context; import android.content.res.TypedArray; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.util.AttributeSet; import android.view.animation.AccelerateDecelerateInterpolator; @@ -79,9 +80,11 @@ public class Animator<T> 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. */ - // 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 @@ public class Animator<T> extends Animatable { /** * 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 @@ public class Animator<T> extends Animatable { 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 class Animator<T> extends Animatable { 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 @@ public class Animator<T> extends Animatable { * @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 @@ public class Animator<T> extends Animatable { * 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 @@ public class Animator<T> extends Animatable { * 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 @@ public class Animator<T> extends Animatable { * @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 @@ public class Animator<T> extends Animatable { * 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 @@ public class Animator<T> extends Animatable { * 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 @@ public class Animator<T> extends Animatable { } /** + * 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 @@ public class Animator<T> extends Animatable { * @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 @@ public class Animator<T> extends Animatable { * @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 @@ public class Animator<T> extends Animatable { 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 @@ public class Animator<T> extends Animatable { */ 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 @@ public class Animator<T> extends Animatable { } } + @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 9366a713971e..022ca7ddc999 100644 --- a/core/java/android/animation/PropertyAnimator.java +++ b/core/java/android/animation/PropertyAnimator.java @@ -21,10 +21,7 @@ import android.content.res.TypedArray; 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 final class PropertyAnimator<T> extends Animator<T> { */ 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 @@ public final class PropertyAnimator<T> extends Animator<T> { @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 @@ public final class PropertyAnimator<T> extends Animator<T> { @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 05e0bc108b28..fc829b84cdaf 100644 --- a/core/java/android/animation/PropertyValuesHolder.java +++ b/core/java/android/animation/PropertyValuesHolder.java @@ -261,11 +261,12 @@ public class PropertyValuesHolder<T> { // 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 2406d8af5722..77494290f9e4 100644 --- a/core/java/android/animation/Sequencer.java +++ b/core/java/android/animation/Sequencer.java @@ -46,10 +46,17 @@ import java.util.HashMap; 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 @@ public final class Sequencer extends Animatable { * 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 @@ public final class Sequencer extends Animatable { } } + @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 @@ public final class Sequencer extends Animatable { * 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 @@ public final class Sequencer extends Animatable { } 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 d8e249ea21f0..4fb4bcad8da1 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3151,7 +3151,7 @@ public final class ActivityThread { (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 274a2664a2e8..a0be0cde1f5d 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -330,7 +330,7 @@ public class Dialog implements DialogInterface, Window.Callback, } /** - * 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 8de2133e4944..6deab34ed483 100644 --- a/core/java/android/bluetooth/AtCommandHandler.java +++ b/core/java/android/bluetooth/AtCommandHandler.java @@ -73,7 +73,7 @@ public abstract class AtCommandHandler { * 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 @@ public abstract class AtCommandHandler { * 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 000000000000..55bc814066ce --- /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 0c9bab24965d..c8381c96a39a 100644 --- a/core/java/android/bluetooth/BluetoothClass.java +++ b/core/java/android/bluetooth/BluetoothClass.java @@ -261,6 +261,10 @@ public final class BluetoothClass implements Parcelable { 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 @@ public final class BluetoothClass implements Parcelable { } } 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 4a91a8c90721..53d6a378616b 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -45,7 +45,7 @@ import android.util.Log; * 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 @@ public final class BluetoothHeadset { "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 final class BluetoothHeadset { 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 fb3dfe43181e..3fbfc70bdb14 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java @@ -55,6 +55,8 @@ public final class BluetoothUuid { 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 @@ public final class BluetoothUuid { 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 e2935c95d324..9ef2eb5f3cec 100644 --- a/core/java/android/bluetooth/HeadsetBase.java +++ b/core/java/android/bluetooth/HeadsetBase.java @@ -74,8 +74,8 @@ public final class HeadsetBase { 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 @@ public final class HeadsetBase { 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 @@ public final class HeadsetBase { (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 @@ public final class HeadsetBase { */ 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 @@ public final class HeadsetBase { 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 @@ public final class HeadsetBase { 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 7901b155467a..244d126b89bb 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -389,15 +389,17 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { 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 155c86cf9f0e..7c6e142c4f4f 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1494,12 +1494,18 @@ public class PackageParser { 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 03aa968831af..38d6526d22e8 100644 --- a/core/java/android/database/DatabaseUtils.java +++ b/core/java/android/database/DatabaseUtils.java @@ -651,14 +651,40 @@ public class DatabaseUtils { * @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 dc3b469c81f8..b83d5ad5c248 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -2066,11 +2066,9 @@ public class SQLiteDatabase extends SQLiteClosable { * 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 @@ public class SQLiteDatabase extends SQLiteClosable { 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 d8cce216db75..ccf8d686de81 100644 --- a/core/java/android/database/sqlite/SQLiteOpenHelper.java +++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java @@ -121,8 +121,13 @@ public abstract class SQLiteOpenHelper { * @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 @@ public abstract class SQLiteOpenHelper { * 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 231d8e6cd650..9b7d823636cb 100644 --- a/core/java/android/database/sqlite/SQLiteProgram.java +++ b/core/java/android/database/sqlite/SQLiteProgram.java @@ -158,18 +158,18 @@ public abstract class SQLiteProgram extends SQLiteClosable { @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 14de60f19e57..dc07db0ed0d2 100644 --- a/core/java/android/database/sqlite/SQLiteStatement.java +++ b/core/java/android/database/sqlite/SQLiteStatement.java @@ -265,7 +265,7 @@ public class SQLiteStatement extends SQLiteProgram 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 a0abc6c0da9e..e432a474b82d 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -960,6 +960,7 @@ public class Camera { 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 class Camera { */ 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 @@ public class Camera { } /** + * 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 @@ public class Camera { 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 @@ public class Camera { return substrings; } + private void splitInt(String str, int[] output) { + if (str == null) return; + + StringTokenizer tokenizer = new StringTokenizer(str, ","); + int index = 0; + while (tokenizer.hasMoreElements()) { + String token = tokenizer.nextToken(); + output[index++] = Integer.parseInt(token); + } + } + // 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 splitFloat(String str, float[] 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++] = Float.parseFloat(token); } - if (substrings.size() == 0) return null; - return substrings; } // Returns the value of a float parameter. @@ -2318,5 +2398,30 @@ public class Camera { 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 b49a409ceef8..f2b907bfd234 100644 --- a/core/java/android/hardware/Sensor.java +++ b/core/java/android/hardware/Sensor.java @@ -77,6 +77,27 @@ public class Sensor { 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 aaf389895d47..2c5c9090eb14 100644 --- a/core/java/android/hardware/SensorEvent.java +++ b/core/java/android/hardware/SensorEvent.java @@ -133,6 +133,16 @@ public class SensorEvent { * 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 @@ public class SensorEvent { * 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 @@ public class SensorEvent { * @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 d2c3eaab353b..97921feea79a 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -1769,6 +1769,183 @@ public class SensorManager } + /** 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 95f217f4e036..9fe6e0136e5b 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -1400,6 +1400,7 @@ public abstract class BatteryStats implements Parcelable { 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 8624467755a1..9268cd17f090 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -206,7 +206,8 @@ public class Build { * <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 49b72fee22d3..eb941e43fe63 100644 --- a/core/java/android/os/Message.java +++ b/core/java/android/os/Message.java @@ -73,7 +73,18 @@ public final class Message implements Parcelable { * 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 @@ public final class Message implements Parcelable { * 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 @@ public final class Message implements Parcelable { } /*package*/ void clearForRecycle() { + flags = 0; what = 0; arg1 = 0; arg2 = 0; @@ -361,6 +374,14 @@ public final class Message implements Parcelable { 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 @@ public final class Message implements Parcelable { replyTo = Messenger.readMessengerOrNullFromParcel(source); } } - diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java index adb11c82f987..75dfdd254960 100644 --- a/core/java/android/os/MessageQueue.java +++ b/core/java/android/os/MessageQueue.java @@ -120,6 +120,7 @@ public class MessageQueue { now = SystemClock.uptimeMillis(); Message msg = pullNextLocked(now); if (msg != null) { + msg.markInUse(); return msg; } @@ -192,7 +193,7 @@ public class MessageQueue { } 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 ac12e1083227..7f7b02b5f1bd 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -114,7 +114,7 @@ public final class StrictMode { * * @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 @@ public final class StrictMode { * * @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 @@ public final class StrictMode { 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 @@ public final class StrictMode { Log.e(TAG, "RemoteException trying to handle StrictMode violation", e); } finally { // Restore the policy. - setThreadBlockingPolicy(savedPolicy); + setThreadPolicy(savedPolicy); } } @@ -487,7 +519,7 @@ public final class StrictMode { 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 5c69214c32c1..000000000000 --- 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 000000000000..60ea95c459f7 --- /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 883413ad103e..000000000000 --- 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 000000000000..d5c5fa579802 --- /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.java b/core/java/android/os/storage/IMountShutdownObserver.java new file mode 100644 index 000000000000..d946e1a7cba5 --- /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 78d7a9ed391c..000000000000 --- 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 000000000000..2c098ac6c911 --- /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 994806051058..3861ef549924 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -644,7 +644,7 @@ class BluetoothEventLoop { } 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 79a0c3767505..3fe14f9b0943 100644 --- a/core/java/android/text/method/ArrowKeyMovementMethod.java +++ b/core/java/android/text/method/ArrowKeyMovementMethod.java @@ -287,8 +287,7 @@ public class ArrowKeyMovementMethod implements MovementMethod { // 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 class ArrowKeyMovementMethod implements MovementMethod { 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 0f39c974a4d9..be442dac630a 100644 --- a/core/java/android/util/TimingLogger.java +++ b/core/java/android/util/TimingLogger.java @@ -24,22 +24,26 @@ import android.os.SystemClock; * 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 132852520f94..74318ba28cc2 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -1319,21 +1319,24 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @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 @@ public final class MotionEvent extends InputEvent implements Parcelable { 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 c13bb8c70fde..b565fc61f9e5 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3438,7 +3438,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } /** - * 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 e2e3333fe720..3678684adf34 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -856,6 +856,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } // 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager 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 abstract class ViewGroup extends View implements ViewParent, ViewManager 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 abstract class ViewGroup extends View implements ViewParent, ViewManager 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return mUniqueTargetCount; } - public View getUniqueTargetAt(int index) { + public TargetInfo getUniqueTargetAt(int index) { return mUniqueTargets[index]; } @@ -4185,18 +4196,29 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager (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 705af0f7f8e8..6633367fddb5 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -771,6 +771,15 @@ public abstract class Window { 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 f3392d9617c0..9a1e41cb2bb9 100644 --- a/core/java/android/view/animation/Animation.java +++ b/core/java/android/view/animation/Animation.java @@ -307,7 +307,7 @@ public abstract class Animation implements Cloneable { * 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 b021ded9a2bd..e972c240ffde 100644 --- a/core/java/android/webkit/BrowserFrame.java +++ b/core/java/android/webkit/BrowserFrame.java @@ -38,6 +38,8 @@ import android.view.WindowManager; 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 @@ class BrowserFrame extends Handler { } /** + * 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 07d3d2fedf82..4ff849ea0162 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; + + private static final double DELTA_DEGRESS = 1.0; - public DeviceOrientationService(DeviceOrientationManager manager) { + public DeviceOrientationService(DeviceOrientationManager manager, Context context) { mManager = manager; assert(mManager != null); + mContext = context; + assert(mContext != null); } public void start() { @@ -55,9 +75,6 @@ final class DeviceOrientationService { 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 @@ final class DeviceOrientationService { } 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 cdcb662e057c..f7d1134d94d6 100644 --- a/core/java/android/webkit/PluginManager.java +++ b/core/java/android/webkit/PluginManager.java @@ -149,41 +149,11 @@ public class PluginManager { 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 @@ public class PluginManager { } /* 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 4823407d2fbd..5d9ab90ae004 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -18,10 +18,14 @@ package android.webkit; 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.Region; 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.io.InputStreamReader; 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 @@ public class WebView extends AbsoluteLayout * such as the mZoomManager. */ init(); + setupPackageListener(context); updateMultiTouchSupport(context); if (privateBrowsing) { @@ -884,6 +891,96 @@ public class WebView extends AbsoluteLayout } } + /* + * 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 @@ public class WebView extends AbsoluteLayout 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 860edf29acaa..fad432323ddf 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -441,6 +441,8 @@ final class WebViewCore { */ 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 @@ final class WebViewCore { 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 @@ final class WebViewCore { 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 0f52fc81e7bb..3a4487c92351 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -21,8 +21,9 @@ import android.content.res.TypedArray; 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.Drawable; 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.Interpolator; 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 @@ public class ProgressBar extends View { } @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 25c5b24b89e0..ec54e9df5276 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -6532,6 +6532,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** * 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int boundTopBefore = bounds.top; convertFromViewportToContentCoordinates(bounds); - mHopSpotVertcalPosition += bounds.top - boundTopBefore; + mHotSpotVerticalPosition += bounds.top - boundTopBefore; mDrawable.setBounds(bounds); postInvalidate(); } @@ -7720,7 +7726,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @hide */ public int getOffset(int x, int y) { - x -= getTotalPaddingLeft(); - y -= getTotalPaddingTop(); + 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; - } + y = Math.max(0, y); + y = Math.min(getHeight() - getTotalPaddingBottom() - 1, y); + y += getScrollY(); - x += getScrollX(); + 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(); - Layout layout = getLayout(); - if (layout != null) { - final int line = layout.getLineForVertical(y); - final int offset = layout.getOffsetForHorizontal(line, x); - return offset; - } else { - return -1; + 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 d1aff2a0bfb8..e07c54f59c34 100644 --- a/core/java/com/android/internal/app/ShutdownThread.java +++ b/core/java/com/android/internal/app/ShutdownThread.java @@ -134,7 +134,7 @@ public final class ShutdownThread extends Thread { 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 a70dbf6a9109..0a1c8ffb17f4 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -3693,8 +3693,8 @@ public final class BatteryStatsImpl extends BatteryStats { 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 0b62a67e70fe..90423beff818 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -19,6 +19,7 @@ package com.android.internal.widget; 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.R; 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.NoSuchAlgorithmException; 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 @@ public class LockPatternUtils { 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 @@ public class LockPatternUtils { 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 class LockPatternUtils { public LockPatternUtils(Context context) { mContext = context; mContentResolver = context.getContentResolver(); - // Initialize the location of gesture lock file + + // Initialize the location of gesture & PIN lock files if (sLockPatternFilename == null) { - sLockPatternFilename = android.os.Environment.getDataDirectory() - .getAbsolutePath() + LOCK_PATTERN_FILE; - sLockPasswordFilename = android.os.Environment.getDataDirectory() - .getAbsolutePath() + LOCK_PASSWORD_FILE; + 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 @@ public class LockPatternUtils { } /** - * 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 @@ public class LockPatternUtils { * @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 17f5daf426c2..f78f83c2a6d9 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -453,30 +453,23 @@ static jint android_media_AudioRecord_get_pos_update_period(JNIEnv *env, jobjec // 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 c55967027654..9d215b72d8be 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -782,29 +782,13 @@ static jint android_media_AudioTrack_get_output_sample_rate(JNIEnv *env, jobjec // 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) { - return -1; - } - if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) { - return -1; - } - - if (AudioSystem::getOutputLatency(&afLatency) != NO_ERROR) { + + int frameCount = 0; + if (AudioTrack::getMinFrameCount(&frameCount, AudioSystem::DEFAULT, + sampleRateInHertz) != 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 Binary files differdeleted file mode 100644 index 97e680664755..000000000000 --- a/core/res/res/drawable-hdpi/btn_check_label_background_light.9.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_check_off.png b/core/res/res/drawable-hdpi/btn_check_off.png Binary files differindex 911e1aa6598c..aad9ef7800fd 100644 --- a/core/res/res/drawable-hdpi/btn_check_off.png +++ b/core/res/res/drawable-hdpi/btn_check_off.png diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable.png b/core/res/res/drawable-hdpi/btn_check_off_disable.png Binary files differindex d72e2b95b810..eaee9e0bec4d 100644 --- a/core/res/res/drawable-hdpi/btn_check_off_disable.png +++ b/core/res/res/drawable-hdpi/btn_check_off_disable.png 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 Binary files differindex d72e2b95b810..6d2c2938a5a5 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 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 Binary files differnew file mode 100644 index 000000000000..d72e2b95b810 --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_dark.png 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 Binary files differindex 240a0444e1eb..240a0444e1eb 100644 --- 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 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 Binary files differnew file mode 100644 index 000000000000..d72e2b95b810 --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_check_off_disable_holo_dark.png 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 Binary files differindex 240a0444e1eb..240a0444e1eb 100644 --- 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 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 Binary files differnew file mode 100644 index 000000000000..911e1aa6598c --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_check_off_holo_dark.png 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 Binary files differindex 4ca3c56d3f3c..4ca3c56d3f3c 100644 --- a/core/res/res/drawable-hdpi/btn_check_off_light.png +++ b/core/res/res/drawable-hdpi/btn_check_off_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_check_off_pressed.png b/core/res/res/drawable-hdpi/btn_check_off_pressed.png Binary files differindex 08f41812ff45..1c442e9b45b9 100644 --- a/core/res/res/drawable-hdpi/btn_check_off_pressed.png +++ b/core/res/res/drawable-hdpi/btn_check_off_pressed.png 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 Binary files differnew file mode 100644 index 000000000000..08f41812ff45 --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png 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 Binary files differindex d3754ddb42ad..d3754ddb42ad 100644 --- 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 diff --git a/core/res/res/drawable-hdpi/btn_check_off_selected.png b/core/res/res/drawable-hdpi/btn_check_off_selected.png Binary files differindex 264f102132ed..b852b2cb2f06 100644 --- a/core/res/res/drawable-hdpi/btn_check_off_selected.png +++ b/core/res/res/drawable-hdpi/btn_check_off_selected.png 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 Binary files differnew file mode 100644 index 000000000000..264f102132ed --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_check_off_selected_holo_dark.png 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 Binary files differindex 48506bf721ba..48506bf721ba 100644 --- 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 diff --git a/core/res/res/drawable-hdpi/btn_check_on.png b/core/res/res/drawable-hdpi/btn_check_on.png Binary files differindex 5541c67ba042..cd5c1814344a 100644 --- a/core/res/res/drawable-hdpi/btn_check_on.png +++ b/core/res/res/drawable-hdpi/btn_check_on.png diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable.png b/core/res/res/drawable-hdpi/btn_check_on_disable.png Binary files differindex 7805458d2cdc..b4fc51a1bf34 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_disable.png +++ b/core/res/res/drawable-hdpi/btn_check_on_disable.png 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 Binary files differindex 7805458d2cdc..bf346471edd5 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 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 Binary files differnew file mode 100644 index 000000000000..7805458d2cdc --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png 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 Binary files differindex 4e268d5168cb..4e268d5168cb 100644 --- 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 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 Binary files differnew file mode 100644 index 000000000000..7805458d2cdc --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_check_on_disable_holo_dark.png 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 Binary files differindex 4e268d5168cb..4e268d5168cb 100644 --- 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 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 Binary files differnew file mode 100644 index 000000000000..5541c67ba042 --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png 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 Binary files differindex 768c4afaed20..768c4afaed20 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_light.png +++ b/core/res/res/drawable-hdpi/btn_check_on_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed.png b/core/res/res/drawable-hdpi/btn_check_on_pressed.png Binary files differindex 37e3953c87b3..fa5c7a23d932 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_pressed.png +++ b/core/res/res/drawable-hdpi/btn_check_on_pressed.png 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 Binary files differnew file mode 100644 index 000000000000..37e3953c87b3 --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png 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 Binary files differindex fc29e46248ab..fc29e46248ab 100644 --- 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 diff --git a/core/res/res/drawable-hdpi/btn_check_on_selected.png b/core/res/res/drawable-hdpi/btn_check_on_selected.png Binary files differindex a0beac44afc8..a6a21adc1e02 100644 --- a/core/res/res/drawable-hdpi/btn_check_on_selected.png +++ b/core/res/res/drawable-hdpi/btn_check_on_selected.png 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 Binary files differnew file mode 100644 index 000000000000..a0beac44afc8 --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_check_on_selected_holo_dark.png 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 Binary files differindex 5df45c74f140..5df45c74f140 100644 --- 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 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 Binary files differdeleted file mode 100644 index 45c5c6a76e19..000000000000 --- a/core/res/res/drawable-hdpi/btn_radio_label_background_light.9.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/btn_radio_off.png b/core/res/res/drawable-hdpi/btn_radio_off.png Binary files differindex 301c97df691b..c0b14aa4db86 100644 --- a/core/res/res/drawable-hdpi/btn_radio_off.png +++ b/core/res/res/drawable-hdpi/btn_radio_off.png 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 Binary files differnew file mode 100644 index 000000000000..301c97df691b --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_radio_off_holo_dark.png 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 Binary files differindex 657c8e55b8e9..657c8e55b8e9 100644 --- a/core/res/res/drawable-hdpi/btn_radio_off_light.png +++ b/core/res/res/drawable-hdpi/btn_radio_off_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_radio_off_pressed.png b/core/res/res/drawable-hdpi/btn_radio_off_pressed.png Binary files differindex 5e6ef2b947df..318958187c0e 100644 --- a/core/res/res/drawable-hdpi/btn_radio_off_pressed.png +++ b/core/res/res/drawable-hdpi/btn_radio_off_pressed.png 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 Binary files differnew file mode 100644 index 000000000000..5e6ef2b947df --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_dark.png 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 Binary files differindex 342bf1168c3f..342bf1168c3f 100644 --- 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 diff --git a/core/res/res/drawable-hdpi/btn_radio_off_selected.png b/core/res/res/drawable-hdpi/btn_radio_off_selected.png Binary files differindex d11ae858a507..f337703e2180 100644 --- a/core/res/res/drawable-hdpi/btn_radio_off_selected.png +++ b/core/res/res/drawable-hdpi/btn_radio_off_selected.png 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 Binary files differnew file mode 100644 index 000000000000..d11ae858a507 --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_dark.png 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 Binary files differindex 68bd1dfee468..68bd1dfee468 100644 --- 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 diff --git a/core/res/res/drawable-hdpi/btn_radio_on.png b/core/res/res/drawable-hdpi/btn_radio_on.png Binary files differindex 5b0dbe842358..c90d2eb05e93 100644 --- a/core/res/res/drawable-hdpi/btn_radio_on.png +++ b/core/res/res/drawable-hdpi/btn_radio_on.png 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 Binary files differnew file mode 100644 index 000000000000..5b0dbe842358 --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_radio_on_holo_dark.png 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 Binary files differindex 45ae36b5e040..45ae36b5e040 100644 --- a/core/res/res/drawable-hdpi/btn_radio_on_light.png +++ b/core/res/res/drawable-hdpi/btn_radio_on_holo_light.png diff --git a/core/res/res/drawable-hdpi/btn_radio_on_pressed.png b/core/res/res/drawable-hdpi/btn_radio_on_pressed.png Binary files differindex c3a0d48f9fab..d79450b8e86a 100644 --- a/core/res/res/drawable-hdpi/btn_radio_on_pressed.png +++ b/core/res/res/drawable-hdpi/btn_radio_on_pressed.png 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 Binary files differnew file mode 100644 index 000000000000..c3a0d48f9fab --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_dark.png 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 Binary files differindex ca223587650a..ca223587650a 100644 --- 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 diff --git a/core/res/res/drawable-hdpi/btn_radio_on_selected.png b/core/res/res/drawable-hdpi/btn_radio_on_selected.png Binary files differindex 6c05f472aca7..db50c437c5a2 100644 --- a/core/res/res/drawable-hdpi/btn_radio_on_selected.png +++ b/core/res/res/drawable-hdpi/btn_radio_on_selected.png 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 Binary files differnew file mode 100644 index 000000000000..6c05f472aca7 --- /dev/null +++ b/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_dark.png 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 Binary files differindex a17fa1edd124..a17fa1edd124 100644 --- 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 diff --git a/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png b/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png Binary files differindex 99a67b977fc6..41b776bb48f4 100644 --- a/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png +++ b/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png 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 Binary files differindex cfe258b1ddff..eb75a22063ba 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 diff --git a/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png b/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png Binary files differindex 338d840c94d6..55a5e5321610 100644 --- a/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png +++ b/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png 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 Binary files differindex 9444f0d18583..60e2cb2d849c 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 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 Binary files differindex 63859f71dcef..cf34613102a7 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 diff --git a/core/res/res/drawable-hdpi/divider_vertical_bright.9.png b/core/res/res/drawable-hdpi/divider_vertical_bright.9.png Binary files differindex 99a67b977fc6..41b776bb48f4 100644 --- a/core/res/res/drawable-hdpi/divider_vertical_bright.9.png +++ b/core/res/res/drawable-hdpi/divider_vertical_bright.9.png 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 Binary files differindex 5c537eec512f..eb75a22063ba 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 diff --git a/core/res/res/drawable-hdpi/divider_vertical_dark.9.png b/core/res/res/drawable-hdpi/divider_vertical_dark.9.png Binary files differindex 702b8785c7cb..55a5e5321610 100644 --- a/core/res/res/drawable-hdpi/divider_vertical_dark.9.png +++ b/core/res/res/drawable-hdpi/divider_vertical_dark.9.png 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 Binary files differindex 8f35315aef86..60e2cb2d849c 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 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 Binary files differnew file mode 100644 index 000000000000..25c624126b3f --- /dev/null +++ b/core/res/res/drawable-hdpi/list_selector_background_default.9.png 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 Binary files differnew file mode 100644 index 000000000000..c3e69f03910d --- /dev/null +++ b/core/res/res/drawable-hdpi/list_selector_background_default_light.9.png 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 Binary files differindex c40233e92adf..ab377d8f0377 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 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 Binary files differnew file mode 100644 index 000000000000..8edc9cdee86b --- /dev/null +++ b/core/res/res/drawable-hdpi/list_selector_background_disabled_light.9.png 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 Binary files differdeleted file mode 100644 index d8e16b996598..000000000000 --- a/core/res/res/drawable-hdpi/list_selector_background_focus.9.png +++ /dev/null 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 Binary files differnew file mode 100644 index 000000000000..60bb4545c5fd --- /dev/null +++ b/core/res/res/drawable-hdpi/list_selector_background_focused.9.png 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 Binary files differnew file mode 100644 index 000000000000..60bb4545c5fd --- /dev/null +++ b/core/res/res/drawable-hdpi/list_selector_background_focused_light.9.png 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 Binary files differnew file mode 100644 index 000000000000..b527da15d83b --- /dev/null +++ b/core/res/res/drawable-hdpi/list_selector_background_focused_selected.9.png 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 Binary files differindex 1676ca71eae6..bd74426710b7 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 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 Binary files differnew file mode 100644 index 000000000000..fc2ba2e3eb28 --- /dev/null +++ b/core/res/res/drawable-hdpi/list_selector_background_longpress_light.9.png 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 Binary files differindex ba79cf7f85d3..d18d6f76d802 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 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 Binary files differnew file mode 100644 index 000000000000..00786e595181 --- /dev/null +++ b/core/res/res/drawable-hdpi/list_selector_background_pressed_light.9.png 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 Binary files differnew file mode 100644 index 000000000000..cbf50b3a10f3 --- /dev/null +++ b/core/res/res/drawable-hdpi/list_selector_background_selected.9.png 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 Binary files differnew file mode 100644 index 000000000000..34ea86ec1bfa --- /dev/null +++ b/core/res/res/drawable-hdpi/list_selector_background_selected_light.9.png 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 Binary files differdeleted file mode 100644 index 79367b8c5393..000000000000 --- a/core/res/res/drawable-mdpi/btn_check_label_background_light.9.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_check_off.png b/core/res/res/drawable-mdpi/btn_check_off.png Binary files differindex 5e44c293ca33..56d3861542ea 100644 --- a/core/res/res/drawable-mdpi/btn_check_off.png +++ b/core/res/res/drawable-mdpi/btn_check_off.png diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable.png b/core/res/res/drawable-mdpi/btn_check_off_disable.png Binary files differindex a603fb1aff9c..e012afd28ddd 100644 --- a/core/res/res/drawable-mdpi/btn_check_off_disable.png +++ b/core/res/res/drawable-mdpi/btn_check_off_disable.png 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 Binary files differindex a603fb1aff9c..0837bbdb89f7 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 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 Binary files differnew file mode 100644 index 000000000000..a603fb1aff9c --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_dark.png 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 Binary files differindex 69e9ff9eb1a2..69e9ff9eb1a2 100644 --- 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 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 Binary files differnew file mode 100644 index 000000000000..a603fb1aff9c --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_check_off_disable_holo_dark.png 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 Binary files differindex 69e9ff9eb1a2..69e9ff9eb1a2 100644 --- 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 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 Binary files differnew file mode 100644 index 000000000000..5e44c293ca33 --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_check_off_holo_dark.png 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 Binary files differindex 5b2ec928e324..5b2ec928e324 100644 --- a/core/res/res/drawable-mdpi/btn_check_off_light.png +++ b/core/res/res/drawable-mdpi/btn_check_off_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_check_off_pressed.png b/core/res/res/drawable-mdpi/btn_check_off_pressed.png Binary files differindex 611bb1d7a05b..984dfd750d30 100644 --- a/core/res/res/drawable-mdpi/btn_check_off_pressed.png +++ b/core/res/res/drawable-mdpi/btn_check_off_pressed.png 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 Binary files differnew file mode 100644 index 000000000000..611bb1d7a05b --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png 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 Binary files differindex 5a0ea441f37a..5a0ea441f37a 100644 --- 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 diff --git a/core/res/res/drawable-mdpi/btn_check_off_selected.png b/core/res/res/drawable-mdpi/btn_check_off_selected.png Binary files differindex aa28df22a4fb..20842d41c8f1 100644 --- a/core/res/res/drawable-mdpi/btn_check_off_selected.png +++ b/core/res/res/drawable-mdpi/btn_check_off_selected.png 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 Binary files differnew file mode 100644 index 000000000000..aa28df22a4fb --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_check_off_selected_holo_dark.png 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 Binary files differindex ade1136e0214..ade1136e0214 100644 --- 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 diff --git a/core/res/res/drawable-mdpi/btn_check_on.png b/core/res/res/drawable-mdpi/btn_check_on.png Binary files differindex 130d5629237c..791ac1d92c32 100644 --- a/core/res/res/drawable-mdpi/btn_check_on.png +++ b/core/res/res/drawable-mdpi/btn_check_on.png diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable.png b/core/res/res/drawable-mdpi/btn_check_on_disable.png Binary files differindex f19972a447b0..6cb02f3e4674 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_disable.png +++ b/core/res/res/drawable-mdpi/btn_check_on_disable.png 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 Binary files differindex f19972a447b0..8a73b33f0df5 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 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 Binary files differnew file mode 100644 index 000000000000..f19972a447b0 --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png 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 Binary files differindex 13ef46e2c39d..13ef46e2c39d 100644 --- 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 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 Binary files differnew file mode 100644 index 000000000000..f19972a447b0 --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_check_on_disable_holo_dark.png 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 Binary files differindex 13ef46e2c39d..13ef46e2c39d 100644 --- 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 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 Binary files differnew file mode 100644 index 000000000000..130d5629237c --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png 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 Binary files differindex 6b7808bbb6a6..6b7808bbb6a6 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_light.png +++ b/core/res/res/drawable-mdpi/btn_check_on_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed.png b/core/res/res/drawable-mdpi/btn_check_on_pressed.png Binary files differindex df753f51eb49..300d64afecb9 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_pressed.png +++ b/core/res/res/drawable-mdpi/btn_check_on_pressed.png 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 Binary files differnew file mode 100644 index 000000000000..df753f51eb49 --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png 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 Binary files differindex 6a4dd2ce7c76..6a4dd2ce7c76 100644 --- 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 diff --git a/core/res/res/drawable-mdpi/btn_check_on_selected.png b/core/res/res/drawable-mdpi/btn_check_on_selected.png Binary files differindex 7586881cc458..0b36adbe2712 100644 --- a/core/res/res/drawable-mdpi/btn_check_on_selected.png +++ b/core/res/res/drawable-mdpi/btn_check_on_selected.png 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 Binary files differnew file mode 100644 index 000000000000..7586881cc458 --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_check_on_selected_holo_dark.png 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 Binary files differindex 24701ce9d59a..24701ce9d59a 100644 --- 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 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 Binary files differdeleted file mode 100644 index 16e89397baec..000000000000 --- a/core/res/res/drawable-mdpi/btn_radio_label_background_light.9.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/btn_radio_off.png b/core/res/res/drawable-mdpi/btn_radio_off.png Binary files differindex 16c1c6bc7b51..407632b1c0d5 100644 --- a/core/res/res/drawable-mdpi/btn_radio_off.png +++ b/core/res/res/drawable-mdpi/btn_radio_off.png 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 Binary files differnew file mode 100644 index 000000000000..16c1c6bc7b51 --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_radio_off_holo_dark.png 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 Binary files differindex e8287f30693e..e8287f30693e 100644 --- a/core/res/res/drawable-mdpi/btn_radio_off_light.png +++ b/core/res/res/drawable-mdpi/btn_radio_off_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_radio_off_pressed.png b/core/res/res/drawable-mdpi/btn_radio_off_pressed.png Binary files differindex b25217b6c214..d6d8a9d4b685 100644 --- a/core/res/res/drawable-mdpi/btn_radio_off_pressed.png +++ b/core/res/res/drawable-mdpi/btn_radio_off_pressed.png 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 Binary files differnew file mode 100644 index 000000000000..b25217b6c214 --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_dark.png 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 Binary files differindex b63b9b0250e6..b63b9b0250e6 100644 --- 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 diff --git a/core/res/res/drawable-mdpi/btn_radio_off_selected.png b/core/res/res/drawable-mdpi/btn_radio_off_selected.png Binary files differindex bef757299c1a..53f3e870e77d 100644 --- a/core/res/res/drawable-mdpi/btn_radio_off_selected.png +++ b/core/res/res/drawable-mdpi/btn_radio_off_selected.png 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 Binary files differnew file mode 100644 index 000000000000..bef757299c1a --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_dark.png 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 Binary files differindex af754e145cfa..af754e145cfa 100644 --- 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 diff --git a/core/res/res/drawable-mdpi/btn_radio_on.png b/core/res/res/drawable-mdpi/btn_radio_on.png Binary files differindex 4ed74712e28c..25a3ccc54e4a 100644 --- a/core/res/res/drawable-mdpi/btn_radio_on.png +++ b/core/res/res/drawable-mdpi/btn_radio_on.png 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 Binary files differnew file mode 100644 index 000000000000..4ed74712e28c --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_radio_on_holo_dark.png 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 Binary files differindex 62aaa41318d1..62aaa41318d1 100644 --- a/core/res/res/drawable-mdpi/btn_radio_on_light.png +++ b/core/res/res/drawable-mdpi/btn_radio_on_holo_light.png diff --git a/core/res/res/drawable-mdpi/btn_radio_on_pressed.png b/core/res/res/drawable-mdpi/btn_radio_on_pressed.png Binary files differindex 7cf91c6c7fa9..c904a35c742b 100644 --- a/core/res/res/drawable-mdpi/btn_radio_on_pressed.png +++ b/core/res/res/drawable-mdpi/btn_radio_on_pressed.png 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 Binary files differnew file mode 100644 index 000000000000..7cf91c6c7fa9 --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_dark.png 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 Binary files differindex 0d93507b66f4..0d93507b66f4 100644 --- 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 diff --git a/core/res/res/drawable-mdpi/btn_radio_on_selected.png b/core/res/res/drawable-mdpi/btn_radio_on_selected.png Binary files differindex 56f6f5b43fa8..78e1fc0227ca 100644 --- a/core/res/res/drawable-mdpi/btn_radio_on_selected.png +++ b/core/res/res/drawable-mdpi/btn_radio_on_selected.png 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 Binary files differnew file mode 100644 index 000000000000..56f6f5b43fa8 --- /dev/null +++ b/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_dark.png 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 Binary files differindex 48dd8e9d3c6c..48dd8e9d3c6c 100644 --- 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 diff --git a/core/res/res/drawable-mdpi/divider_horizontal_bright.9.png b/core/res/res/drawable-mdpi/divider_horizontal_bright.9.png Binary files differindex 395227a00db0..41b776bb48f4 100644 --- a/core/res/res/drawable-mdpi/divider_horizontal_bright.9.png +++ b/core/res/res/drawable-mdpi/divider_horizontal_bright.9.png 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 Binary files differindex 5c537eec512f..eb75a22063ba 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 diff --git a/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png b/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png Binary files differindex bf45e38f0744..55a5e5321610 100644 --- a/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png +++ b/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png 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 Binary files differindex 9444f0d18583..60e2cb2d849c 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 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 Binary files differindex 08838cafa815..cf34613102a7 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 diff --git a/core/res/res/drawable-mdpi/divider_vertical_bright.9.png b/core/res/res/drawable-mdpi/divider_vertical_bright.9.png Binary files differindex 395227a00db0..41b776bb48f4 100644 --- a/core/res/res/drawable-mdpi/divider_vertical_bright.9.png +++ b/core/res/res/drawable-mdpi/divider_vertical_bright.9.png 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 Binary files differindex 5c537eec512f..eb75a22063ba 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 diff --git a/core/res/res/drawable-mdpi/divider_vertical_dark.9.png b/core/res/res/drawable-mdpi/divider_vertical_dark.9.png Binary files differindex 702b8785c7cb..55a5e5321610 100644 --- a/core/res/res/drawable-mdpi/divider_vertical_dark.9.png +++ b/core/res/res/drawable-mdpi/divider_vertical_dark.9.png 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 Binary files differindex 8f35315aef86..60e2cb2d849c 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 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 Binary files differnew file mode 100644 index 000000000000..cac71b02bce0 --- /dev/null +++ b/core/res/res/drawable-mdpi/list_selector_background_default.9.png 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 Binary files differnew file mode 100644 index 000000000000..bdedffdd8f52 --- /dev/null +++ b/core/res/res/drawable-mdpi/list_selector_background_default_light.9.png 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 Binary files differindex bf970b0509b8..60f19fe459eb 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 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 Binary files differnew file mode 100644 index 000000000000..bc9926126b88 --- /dev/null +++ b/core/res/res/drawable-mdpi/list_selector_background_disabled_light.9.png 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 Binary files differdeleted file mode 100644 index c3e241586642..000000000000 --- a/core/res/res/drawable-mdpi/list_selector_background_focus.9.png +++ /dev/null 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 Binary files differnew file mode 100644 index 000000000000..5b1f19526f12 --- /dev/null +++ b/core/res/res/drawable-mdpi/list_selector_background_focused.9.png 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 Binary files differnew file mode 100644 index 000000000000..5b1f19526f12 --- /dev/null +++ b/core/res/res/drawable-mdpi/list_selector_background_focused_light.9.png 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 Binary files differnew file mode 100644 index 000000000000..e5b0c1db0aae --- /dev/null +++ b/core/res/res/drawable-mdpi/list_selector_background_focused_selected.9.png 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 Binary files differindex 5cbb251a7dbf..78176673d570 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 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 Binary files differnew file mode 100644 index 000000000000..646fc6902d62 --- /dev/null +++ b/core/res/res/drawable-mdpi/list_selector_background_longpress_light.9.png 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 Binary files differindex 02b4e9a536fe..1531d9dd2728 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 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 Binary files differnew file mode 100644 index 000000000000..fdf6f491f337 --- /dev/null +++ b/core/res/res/drawable-mdpi/list_selector_background_pressed_light.9.png 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 Binary files differnew file mode 100644 index 000000000000..a4ac1e30ca16 --- /dev/null +++ b/core/res/res/drawable-mdpi/list_selector_background_selected.9.png 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 Binary files differnew file mode 100644 index 000000000000..d086194d0619 --- /dev/null +++ b/core/res/res/drawable-mdpi/list_selector_background_selected_light.9.png diff --git a/core/res/res/drawable/btn_check_light.xml b/core/res/res/drawable/btn_check_holo_dark.xml index 85f119a3151a..fd85d72d00e1 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_holo_light.xml b/core/res/res/drawable/btn_check_holo_light.xml new file mode 100644 index 000000000000..4fb16faf4ec0 --- /dev/null +++ b/core/res/res/drawable/btn_check_holo_light.xml @@ -0,0 +1,65 @@ +<?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"> + + <!-- Enabled states --> + + <item android:state_checked="true" android:state_window_focused="false" + android:state_enabled="true" + 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_holo_light" /> + + <item android:state_checked="true" android:state_pressed="true" + android:state_enabled="true" + 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_holo_light" /> + + <item android:state_checked="true" android:state_focused="true" + android:state_enabled="true" + 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_holo_light" /> + + <item android:state_checked="false" + android:state_enabled="true" + android:drawable="@drawable/btn_check_off_holo_light" /> + <item android:state_checked="true" + android:state_enabled="true" + 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_holo_light" /> + <item android:state_checked="false" android:state_window_focused="false" + 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_holo_light" /> + <item android:state_checked="false" android:state_focused="true" + android:drawable="@drawable/btn_check_off_disable_focused_holo_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 index 51c930bae4c6..8984f6da63e4 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_holo_light.xml b/core/res/res/drawable/btn_radio_holo_light.xml new file mode 100644 index 000000000000..001508c404ba --- /dev/null +++ b/core/res/res/drawable/btn_radio_holo_light.xml @@ -0,0 +1,35 @@ +<?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_checked="true" android:state_window_focused="false" + android:drawable="@drawable/btn_radio_on_holo_light" /> + <item android:state_checked="false" android:state_window_focused="false" + android:drawable="@drawable/btn_radio_off_holo_light" /> + + <item android:state_checked="true" android:state_pressed="true" + 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_holo_light" /> + + <item android:state_checked="true" android:state_focused="true" + 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_holo_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 000000000000..2bb65945b11c --- /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 000000000000..15fc1cb4ccf0 --- /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 bca996c9ed23..0a511528a145 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 000000000000..9b7980c60062 --- /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 000000000000..634f89525395 --- /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 5785d3b54fa4..b646a4c1eadc 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 3560fee02054..c3c20731e655 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 000000000000..518bcd0fcbd4 --- /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 3de378bee211..1cbfbbaad9e9 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 2ec6b0b02c48..09a84906c0ee 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 05f30fca350f..fdc0d6961569 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 fe8a8166167e..be2752821e08 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 30c51844d377..e9a4ca36fa80 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 ea5c1586d784..ddd3c006afae 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 37b66d3099d1..696480820765 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 c78705b415c3..3ebe7cb85cee 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 dc5613e9ca3d..86eda710266f 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 @@ package android.database.sqlite; 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 @@ public class SQLiteDatabaseTest extends AndroidTestCase { 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 @@ public class SQLiteDatabaseTest extends AndroidTestCase { 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 @@ public class SQLiteDatabaseTest extends AndroidTestCase { "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 @@ public class SQLiteDatabaseTest extends AndroidTestCase { /** * 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 @@ public class SQLiteDatabaseTest extends AndroidTestCase { "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 f3b7c06a853b..95aad91a6f10 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.Reader; 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 b7c2d1f1c149..f82bfce6ef4e 100644 --- a/core/tests/coretests/src/android/os/MessageQueueTest.java +++ b/core/tests/coretests/src/android/os/MessageQueueTest.java @@ -41,6 +41,10 @@ public class MessageQueueTest extends TestCase { } 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 @@ public class MessageQueueTest extends TestCase { 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 d0318cfba096..35ce17e26eae 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 f780e7c6bfce..6d6abd8b15c9 100644 --- a/docs/html/guide/topics/fundamentals.jd +++ b/docs/html/guide/topics/fundamentals.jd @@ -770,9 +770,9 @@ return to what that instance was doing before the new intent arrived. </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 e988ecbc454e..5f98902cf701 100644 --- a/docs/html/guide/topics/location/index.jd +++ b/docs/html/guide/topics/location/index.jd @@ -4,94 +4,63 @@ page.title=Location and Maps <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 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 more information, read the guide to <a +href="{@docRoot}guide/topics/location/obtaining-user-location.html">Obtaining User +Location</a>.</p> -<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 @@ Google APIs add-on, visit</p> <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 000000000000..bc782d2e9734 --- /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 de8ca6d8950b..e030a4c48e5e 100644 --- a/docs/html/guide/topics/manifest/activity-element.jd +++ b/docs/html/guide/topics/manifest/activity-element.jd @@ -336,10 +336,10 @@ it can also be set as a raw string. </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 @@ The default mode is "{@code standard}". </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 Binary files differnew file mode 100644 index 000000000000..d58bfeeed2fe --- /dev/null +++ b/docs/html/images/location/content-tagging.png diff --git a/docs/html/images/location/getting-location.png b/docs/html/images/location/getting-location.png Binary files differnew file mode 100644 index 000000000000..a5905ecd46ab --- /dev/null +++ b/docs/html/images/location/getting-location.png diff --git a/docs/html/images/location/where-to-go.png b/docs/html/images/location/where-to-go.png Binary files differnew file mode 100644 index 000000000000..59f5983a367a --- /dev/null +++ b/docs/html/images/location/where-to-go.png diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java index f1f673b393df..6775c08019fa 100644 --- a/graphics/java/android/renderscript/Allocation.java +++ b/graphics/java/android/renderscript/Allocation.java @@ -395,6 +395,17 @@ public class Allocation extends BaseObj { 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 08065cf3e7f9..fd89b6ec5929 100644 --- a/graphics/java/android/renderscript/ProgramRaster.java +++ b/graphics/java/android/renderscript/ProgramRaster.java @@ -67,17 +67,46 @@ public class ProgramRaster extends BaseObj { 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 @@ public class ProgramRaster extends BaseObj { 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 e24984221b76..32c0d013da70 100644 --- a/graphics/java/android/renderscript/ProgramStore.java +++ b/graphics/java/android/renderscript/ProgramStore.java @@ -79,139 +79,139 @@ public class ProgramStore extends BaseObj { 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 37c01f5e500a..ab1d7650866a 100644 --- a/graphics/java/android/renderscript/RenderScript.java +++ b/graphics/java/android/renderscript/RenderScript.java @@ -549,19 +549,22 @@ public class RenderScript { 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 ccd46bd65146..343fcdb55501 100644 --- a/graphics/java/android/renderscript/Sampler.java +++ b/graphics/java/android/renderscript/Sampler.java @@ -78,7 +78,7 @@ public class Sampler extends BaseObj { 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 @@ public class Sampler extends BaseObj { 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 964700b9fd83..75cf5ffeff16 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 @@ public: 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 1529db71885e..515d87991c72 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 @@ class CameraHardwareInterface : public virtual RefBase { 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 @@ public: */ 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 4bc1799f2991..a5c7874e0add 100644 --- a/include/camera/CameraParameters.h +++ b/include/camera/CameraParameters.h @@ -61,6 +61,7 @@ public: 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 @@ public: // 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 6fcf9e5aa7d7..8bceea5dce6c 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 @@ public: // 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 af9a7edf9966..a1ce113d80f3 100644 --- a/include/media/IMediaPlayer.h +++ b/include/media/IMediaPlayer.h @@ -25,6 +25,7 @@ namespace android { class Parcel; class ISurface; +class Surface; class IMediaPlayer: public IInterface { @@ -33,7 +34,8 @@ public: 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 54adca8d09f7..54b197cdfd55 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 @@ public: 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 @@ public: }; // namespace android #endif // ANDROID_IMEDIARECORDER_H - diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 36629836b52a..13c73accc772 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -33,6 +33,7 @@ namespace android { class Parcel; class ISurface; +class Surface; template<typename T> class SortedVector; @@ -104,7 +105,8 @@ public: 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 5e9e3681a672..e5edd29f1b31 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 @@ struct MediaRecorderBase { 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 c091c39b3f6a..4b44ccc551ec 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 @@ public: 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 @@ private: }; // namespace android #endif // ANDROID_PVMEDIARECORDER_H - diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h index df5098121d70..657e7a673465 100644 --- a/include/media/PVPlayer.h +++ b/include/media/PVPlayer.h @@ -43,7 +43,8 @@ public: 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 5d51de8374f1..b8746c295baa 100644 --- a/include/media/Visualizer.h +++ b/include/media/Visualizer.h @@ -151,7 +151,6 @@ private: 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 de82b38c0fab..2412f6a8010b 100644 --- a/include/media/stagefright/MPEG4Writer.h +++ b/include/media/stagefright/MPEG4Writer.h @@ -40,6 +40,7 @@ public: 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 151bf1639620..5cc8dcffe0d1 100644 --- a/include/media/stagefright/MediaWriter.h +++ b/include/media/stagefright/MediaWriter.h @@ -44,6 +44,10 @@ struct MediaWriter : public RefBase { 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 000000000000..a2735a4e594a --- /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 000000000000..5b1f21cf98b5 --- /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 000000000000..d019e019bc0d --- /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 000000000000..1bedcc69e13c --- /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 294c867c37bd..6fdd2ae7ba6f 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -94,7 +94,7 @@ private: 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 @@ private: * (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 @@ private: }; // namespace android #endif // ANDROID_SF_SURFACE_H - diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp index 7efc6d781448..b5f78e8a0d10 100644 --- a/libs/camera/Camera.cpp +++ b/libs/camera/Camera.cpp @@ -167,32 +167,20 @@ status_t Camera::unlock() 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 @@ void Camera::DeathNotifier::binderDied(const wp<IBinder>& who) { } }; // namespace android - diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp index abd418a4daef..d0ed7df59257 100644 --- a/libs/camera/CameraParameters.cpp +++ b/libs/camera/CameraParameters.cpp @@ -30,6 +30,8 @@ const char CameraParameters::KEY_PREVIEW_FORMAT[] = "preview-format"; 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 @@ void CameraParameters::remove(const char *key) 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 @@ static void parseSizesList(const char *sizesStr, Vector<Size> &sizes) 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::setPreviewSize(int width, int height) 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 @@ int CameraParameters::getPreviewFrameRate() const 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::setPictureSize(int width, int height) 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 13673b53ea4c..94dc5c184f0d 100644 --- a/libs/camera/ICamera.cpp +++ b/libs/camera/ICamera.cpp @@ -64,13 +64,13 @@ public: 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 @@ status_t BnCamera::onTransact( 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 @@ status_t BnCamera::onTransact( // ---------------------------------------------------------------------------- }; // namespace android - diff --git a/libs/rs/java/Samples/res/drawable/torusmap.png b/libs/rs/java/Samples/res/drawable/torusmap.png Binary files differnew file mode 100644 index 000000000000..1e08f3b9ac3e --- /dev/null +++ b/libs/rs/java/Samples/res/drawable/torusmap.png diff --git a/libs/rs/java/Samples/res/raw/torus.a3d b/libs/rs/java/Samples/res/raw/torus.a3d Binary files differnew file mode 100644 index 000000000000..610f0952f4a0 --- /dev/null +++ b/libs/rs/java/Samples/res/raw/torus.a3d 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 5a6ff2350713..8eff455f6116 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 @@ public class RsRenderStatesRS { 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 @@ public class RsRenderStatesRS { 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 @@ public class RsRenderStatesRS { 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 @@ public class RsRenderStatesRS { 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 @@ public class RsRenderStatesRS { 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 @@ public class RsRenderStatesRS { 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 1526a5064089..68d9d3ce1e37 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_vertex gProgVertex; 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 @@ rs_font gFontMono; 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 @@ void displayFontSamples() { 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 @@ void displayShaderSamples() { // 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 displayShaderSamples() { void displayBlendingSamples() { int i; - rsgBindProgramVertex(gProgVertex); + bindProgramVertexOrtho(); rs_matrix4x4 matrix; rsMatrixLoadIdentity(&matrix); rsgProgramVertexLoadModelMatrix(&matrix); @@ -168,11 +196,128 @@ void displayBlendingSamples() { } 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 @@ int root(int launchID) { 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 000000000000..1e52fa438179 --- /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 000000000000..902bb27d020d --- /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 000000000000..c98a42461b15 --- /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 000000000000..1a6fdeeac1d9 --- /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 000000000000..5bfece7c9066 --- /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 000000000000..e69de29bb2d1 --- /dev/null +++ b/libs/storage/MODULE_LICENSE_APACHE2 diff --git a/libs/storage/NOTICE b/libs/storage/NOTICE new file mode 100644 index 000000000000..5d142934114f --- /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 156a7db3c190..47ec78a7dd13 100644 --- a/libs/surfaceflinger_client/SharedBufferStack.cpp +++ b/libs/surfaceflinger_client/SharedBufferStack.cpp @@ -344,11 +344,6 @@ ssize_t SharedBufferClient::dequeue() { 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 5ab72cd3710a..f52447650a39 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/surfaceflinger_client/Surface.cpp @@ -363,6 +363,13 @@ status_t Surface::writeToParcel( 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 @@ void Surface::init() 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 a4c3500dcce9..604f55876e55 100644 --- a/libs/utils/ZipFileRO.cpp +++ b/libs/utils/ZipFileRO.cpp @@ -636,7 +636,7 @@ bool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer) const memcpy(buffer, ptr, uncompLen); } else { if (!inflateBuffer(buffer, ptr, uncompLen, compLen)) - goto bail; + goto unmap; } if (compLen > kSequentialMin) @@ -644,6 +644,8 @@ bool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer) const result = true; +unmap: + file->release(); bail: return result; } @@ -667,7 +669,7 @@ bool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const 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 @@ bool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const 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 7f91c22b9296..7d8ef581d6f0 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -556,7 +556,8 @@ public class MediaScanner 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 abbea30ff575..bf831728f791 100644 --- a/media/jni/android_media_MtpDatabase.cpp +++ b/media/jni/android_media_MtpDatabase.cpp @@ -118,6 +118,18 @@ public: 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 @@ MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path, 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 @@ void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle, 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 @@ MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID, 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 @@ MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() { 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 @@ MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() { 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 @@ MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectForm 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 @@ MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() { 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 @@ MtpResponseCode MyMtpDatabase::getObjectProperty(MtpObjectHandle handle, LOGE("unsupported object type\n"); return MTP_RESPONSE_INVALID_OBJECT_HANDLE; } + + checkAndClearExceptionFromCallback(env, __FUNCTION__); return MTP_RESPONSE_OK; } @@ -368,6 +401,7 @@ MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle, packet.putString(date); // date modified packet.putEmptyString(); // keywords + checkAndClearExceptionFromCallback(env, __FUNCTION__); return MTP_RESPONSE_OK; } @@ -388,12 +422,16 @@ MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle, 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 @@ MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) 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 @@ MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle, MtpOb 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 a944212c6aa6..ff34707ad5dd 100644 --- a/media/libeffects/lvm/lib/Android.mk +++ b/media/libeffects/lvm/lib/Android.mk @@ -122,3 +122,58 @@ LOCAL_C_INCLUDES += \ $(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 8cf84b7e3c81..4a9dc72cf817 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 LVDBE_SetFilters(LVDBE_Instance_t *pInstance, (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 LVDBE_SetFilters(LVDBE_Instance_t *pInstance, (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_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t hInstance, { LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance; + LVMixer3_2St_st *pBypassMixer_Instance = &pInstance->pData->BypassMixer; /* @@ -339,6 +340,14 @@ LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t hInstance, { 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 @@ LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t hInstance, 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 75869c773a7f..95c421dec80b 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_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t *phInstance, LVDBE_Instance_t *pInstance; LVMixer3_1St_st *pMixer_Instance; + LVMixer3_2St_st *pBypassMixer_Instance; LVM_INT16 i; LVM_INT32 MixGain; @@ -227,7 +228,7 @@ LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t *phInstance, /* * 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_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t *phInstance, */ 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_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t *phInstance, 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 @@ LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t *phInstance, 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 3e09cf4e54bf..df32873a7a8d 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 @@ extern "C" { #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 @@ typedef struct 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 @@ typedef struct /* 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 35eec0715594..04032c02cc56 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_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance, 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 @@ LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance, /* * 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 @@ LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance, */ 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 @@ LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance, */ 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 922f77d2bae1..cec7501fc2d5 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 000000000000..4c32db0c9b7b --- /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 000000000000..0026652bea90 --- /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 000000000000..b02b1a7ea28f --- /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 000000000000..ebf145e30f75 --- /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 000000000000..ca1c84d1378b --- /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 000000000000..e16a3d30b89e --- /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 000000000000..896b051878cc --- /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 000000000000..822ac8f033ab --- /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 000000000000..124fd3bcf49c --- /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 000000000000..9249a3151c4b --- /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 000000000000..98471be9cdee --- /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 fea44bfca4fb..668b151cfeab 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 7ab6571774a1..d8023d6405b7 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 f5f7cd0d5741..82a8db2a507f 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 b67d824f2a55..83748e6de6b7 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 7855dcd4fceb..2e9b9b41d539 100644 --- a/media/libeffects/lvm/wrapper/Android.mk +++ b/media/libeffects/lvm/wrapper/Android.mk @@ -34,3 +34,36 @@ LOCAL_C_INCLUDES += \ 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 bcd646a34f34..798271effffb 100644 --- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp +++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp @@ -66,7 +66,9 @@ namespace { // 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_enable (EffectContext *pContext); 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 @@ extern "C" int EffectCreate(effect_uuid_t *uuid, int32_t ioId, effect_interface_t *pInterface){ int ret; + int sessionNo; int i; EffectContext *pContext = new EffectContext; @@ -199,7 +202,7 @@ extern "C" int EffectCreate(effect_uuid_t *uuid, 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 @@ extern "C" int EffectCreate(effect_uuid_t *uuid, 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); + + LvmSessionsActive++; + + 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[sessionId].bBundledEffectsEnabled = LVM_TRUE; - GlobalSessionMemory[sessionId].pBundledContext = new BundledEffectContext; + GlobalSessionMemory[sessionNo].bBundledEffectsEnabled = LVM_TRUE; + GlobalSessionMemory[sessionNo].pBundledContext = new BundledEffectContext; - pContext->pBundledContext = GlobalSessionMemory[sessionId].pBundledContext; - pContext->pBundledContext->SessionNo = sessionId; + 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 @@ extern "C" int EffectCreate(effect_uuid_t *uuid, } } 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 @@ extern "C" int EffectRelease(effect_interface_t interface){ 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 @@ extern "C" int EffectRelease(effect_interface_t interface){ 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 @@ void LvmGlobalBundle_init(){ GlobalSessionMemory[i].bBassInstantiated = LVM_FALSE; GlobalSessionMemory[i].bVirtualizerInstantiated = LVM_FALSE; GlobalSessionMemory[i].pBundledContext = LVM_NULL; + + SessionIndex[i] = -1; } return; } @@ -505,6 +553,9 @@ int LvmBundle_init(EffectContext *pContext){ 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 @@ int Effect_configure(EffectContext *pContext, effect_config_t *pConfig){ 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 @@ int Effect_configure(EffectContext *pContext, effect_config_t *pConfig){ 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 @@ int VolumeSetStereoPosition(EffectContext *pContext, int16_t position){ 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 @@ int32_t VolumeEnableStereoPosition(EffectContext *pContext, uint32_t enabled){ //---------------------------------------------------------------------------- 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_getParameter(EffectContext *pContext, // //---------------------------------------------------------------------------- -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 @@ int BassBoost_setParameter (EffectContext *pContext, int32_t *pParam, void *pVal //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 BassBoost_setParameter (EffectContext *pContext, int32_t *pParam, void *pVal //---------------------------------------------------------------------------- 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_getParameter(EffectContext *pContext, // //---------------------------------------------------------------------------- -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 @@ int Virtualizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pV //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 Virtualizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pV // //---------------------------------------------------------------------------- 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 @@ int Equalizer_getParameter(EffectContext *pContext, break; case EQ_PARAM_BAND_LEVEL: - param2 = *pParam; + param2 = *pParamTemp; if (param2 >= FIVEBAND_NUMBANDS) { status = -EINVAL; break; @@ -1935,7 +1999,7 @@ int Equalizer_getParameter(EffectContext *pContext, break; case EQ_PARAM_CENTER_FREQ: - param2 = *pParam; + param2 = *pParamTemp; if (param2 >= FIVEBAND_NUMBANDS) { status = -EINVAL; break; @@ -1946,7 +2010,7 @@ int Equalizer_getParameter(EffectContext *pContext, break; case EQ_PARAM_BAND_FREQ_RANGE: - param2 = *pParam; + param2 = *pParamTemp; if (param2 >= FIVEBAND_NUMBANDS) { status = -EINVAL; break; @@ -1957,7 +2021,7 @@ int Equalizer_getParameter(EffectContext *pContext, 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 @@ int Equalizer_getParameter(EffectContext *pContext, 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 @@ int Equalizer_getParameter(EffectContext *pContext, // 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 @@ int Equalizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pVal 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 Equalizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pVal //---------------------------------------------------------------------------- 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_getParameter(EffectContext *pContext, // //---------------------------------------------------------------------------- -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 @@ int Volume_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue) 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 @@ extern "C" int Effect_process(effect_interface_t self, 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 @@ extern "C" int Effect_process(effect_interface_t self, } 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 @@ extern "C" int Effect_process(effect_interface_t self, } } - if(status != -ENODATA){ + if((status2Sec != -ENODATA)&&(status != -ENODATA)){ pContext->pBundledContext->NumberEffectsCalled++; } @@ -2496,7 +2599,7 @@ extern "C" int Effect_command(effect_interface_t self, 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 @@ extern "C" int Effect_command(effect_interface_t self, 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 @@ extern "C" int Effect_command(effect_interface_t self, 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 @@ extern "C" int Effect_command(effect_interface_t self, 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 @@ extern "C" int Effect_command(effect_interface_t self, // 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 @@ extern "C" int Effect_command(effect_interface_t self, // 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 @@ extern "C" int Effect_command(effect_interface_t self, 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 @@ extern "C" int Effect_command(effect_interface_t self, 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 @@ extern "C" int Effect_command(effect_interface_t self, *(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 @@ extern "C" int Effect_command(effect_interface_t self, } 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 d009bf926737..1bee974a3cba 100644 --- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h +++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h @@ -58,6 +58,7 @@ struct PresetConfig { 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 @@ struct BundledEffectContext{ 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 000000000000..2043e44b008c --- /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/core/java/android/os/storage/IMountShutdownObserver.aidl b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h index 0aa8a4592ab6..1ab423f5f47c 100644..100755 --- a/core/java/android/os/storage/IMountShutdownObserver.aidl +++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Android Open Source Project + * 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. @@ -14,20 +14,25 @@ * limitations under the License. */ -package android.os.storage; +#ifndef ANDROID_EFFECTREVERB_H_ +#define ANDROID_EFFECTREVERB_H_ -/** - * 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); -} +#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 977e6be04776..b4d01f57d02c 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -31,7 +31,8 @@ LOCAL_SRC_FILES:= \ 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 @@ LOCAL_C_INCLUDES := \ $(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 0f55b19dc82e..9dfdcb0ee3b9 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 @@ public: 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 @@ status_t BnMediaPlayer::onTransact( 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 947ff3409390..f55a01ebdb61 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 @@ public: 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 @@ status_t BnMediaRecorder::onTransact( 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 32cdb491e387..39552b64a85c 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 @@ Visualizer::Visualizer (int32_t priority, 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 @@ status_t Visualizer::setCaptureSize(uint32_t size) } 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::getFft(uint8_t *fft) 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 000000000000..28eb05a6573e --- /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 f3229c074b20..32b20c7bf95f 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -206,10 +206,15 @@ status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface) 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 9d53c257e930..7f253599189e 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -65,7 +65,7 @@ status_t MediaRecorder::setPreviewSurface(const sp<Surface>& surface) 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 @@ void MediaRecorder::died() } }; // namespace android - diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index b5972e761f54..d9b0c696611d 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -889,7 +889,15 @@ status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64 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 a967ee24cd92..deb458cd841b 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -204,7 +204,8 @@ private: // 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 73862c3a0ae0..7e050435703d 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -70,7 +70,7 @@ status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera) 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 @@ status_t MediaRecorderClient::dump(int fd, const Vector<String16>& args) const { } }; // namespace android - diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h index 1d1913dfe2f0..6c172179a15f 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -29,7 +29,7 @@ class MediaRecorderClient : public BnMediaRecorder { 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 @@ private: }; // namespace android #endif // ANDROID_MEDIARECORDERCLIENT_H - diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h index 4a60ece7a0db..06e4b7042d83 100644 --- a/media/libmediaplayerservice/MidiFile.h +++ b/media/libmediaplayerservice/MidiFile.h @@ -35,7 +35,8 @@ public: 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 2c96d6d2b2e3..6b9bf85917ed 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.cpp +++ b/media/libmediaplayerservice/StagefrightPlayer.cpp @@ -44,13 +44,20 @@ status_t StagefrightPlayer::setDataSource(int fd, int64_t offset, int64_t length 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 781eb442736f..dd371023299f 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.h +++ b/media/libmediaplayerservice/StagefrightPlayer.h @@ -35,7 +35,8 @@ public: 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 59a544c70f26..a24e56c6b4e4 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 @@ status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { 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::setParamVideoEncodingBitRate(int32_t bitRate) { 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 @@ status_t StagefrightRecorder::getMaxAmplitude(int *max) { 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 a8be27d3fa8f..628e19bd195b 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -42,7 +42,7 @@ struct StagefrightRecorder : public MediaRecorderBase { 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 @@ private: }; sp<Camera> mCamera; - sp<ISurface> mPreviewSurface; + sp<Surface> mPreviewSurface; sp<IMediaRecorderClient> mListener; sp<MediaWriter> mWriter; sp<AudioSource> mAudioSourceNode; @@ -144,4 +144,3 @@ private: } // namespace android #endif // STAGEFRIGHT_RECORDER_H_ - diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h index 6e6c3cd13175..5eaf5923bd36 100644 --- a/media/libmediaplayerservice/TestPlayerStub.h +++ b/media/libmediaplayerservice/TestPlayerStub.h @@ -75,7 +75,10 @@ class TestPlayerStub : public MediaPlayerInterface { // 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 f2653cf5f1d8..b7beb6b06fd6 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 @@ struct AwesomeLocalRenderer : public AwesomeRenderer { 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 @@ private: 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 @@ void AwesomeLocalRenderer::init( 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 @@ void AwesomeLocalRenderer::init( if (func) { mTarget = - (*func)(surface, componentName, colorFormat, + (*func)(isurface, componentName, colorFormat, displayWidth, displayHeight, decodedWidth, decodedHeight); } @@ -619,8 +622,18 @@ status_t AwesomePlayer::play_l() { 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,17 +650,7 @@ void AwesomePlayer::initRenderer_l() { // before creating a new one. IPCThreadState::self()->flushCommands(); - if (!strncmp("OMX.", component, 4)) { - // Our OMX codecs allocate buffers on the media_server side - // therefore they require a remote IOMXRenderer that knows how - // to display them. - mVideoRenderer = new AwesomeRemoteRenderer( - mClient.interface()->createRenderer( - mISurface, component, - (OMX_COLOR_FORMATTYPE)format, - decodedWidth, decodedHeight, - mVideoWidth, mVideoHeight)); - } else { + if (mSurface != NULL) { // Other decoders are instantiated locally and as a consequence // allocate their buffers in local address space. mVideoRenderer = new AwesomeLocalRenderer( @@ -655,8 +658,19 @@ void AwesomePlayer::initRenderer_l() { 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. + mVideoRenderer = new AwesomeRemoteRenderer( + mClient.interface()->createRenderer( + mISurface, component, + (OMX_COLOR_FORMATTYPE)format, + decodedWidth, decodedHeight, + mVideoWidth, mVideoHeight)); } } } @@ -695,6 +709,12 @@ void AwesomePlayer::setISurface(const sp<ISurface> &isurface) { 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 @@ void AwesomePlayer::onVideoEvent() { if (err == INFO_FORMAT_CHANGED) { LOGV("VideoSource signalled format change."); + notifyVideoSize_l(); + if (mVideoRenderer != NULL) { mVideoRendererIsPreview = false; initRenderer_l(); @@ -1422,10 +1444,10 @@ void AwesomePlayer::onPrepareAsyncEvent() { 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 @@ status_t AwesomePlayer::resume() { 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 6bb54bdd4f49..e36d9feba1c0 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -60,6 +60,7 @@ public: 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 @@ private: // 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 @@ MPEG4Writer::~MPEG4Writer() { 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 @@ status_t MPEG4Writer::Track::threadEntry() { 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 @@ status_t MPEG4Writer::Track::threadEntry() { if (mSampleSizes.empty()) { err = ERROR_MALFORMED; + } else if (OK != checkCodecSpecificData()) { + err = ERROR_MALFORMED; } mOwner->trackProgressStatus(this, -1, err); @@ -1833,6 +1884,27 @@ int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { 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 4741b1d84e80..b39157e09d95 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -146,29 +146,36 @@ static sp<MediaSource> InstantiateSoftwareCodec( 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 @@ static const CodecInfo kEncoderInfo[] = { { 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 @@ static int CompareSoftwareCodecsFirst( 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 @@ void OMXCodec::setVideoInputFormat( 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 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) { 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 389180c82bdd..52a391f691ff 100644 --- a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp +++ b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp @@ -338,10 +338,15 @@ status_t AVCEncoder::read( MediaBuffer *outputBuffer; CHECK_EQ(OK, mGroup->acquire_buffer(&outputBuffer)); - - // Add 4 bytes for the start code 0x00000001 - uint8_t *outPtr = (uint8_t *) outputBuffer->data() + 4; - uint32_t dataLength = outputBuffer->size() - 4; + uint8_t *outPtr = (uint8_t *) outputBuffer->data(); + uint32_t dataLength = outputBuffer->size(); + + 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 @@ status_t AVCEncoder::read( 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 b9ba1be6a772..2b63235851cf 100644 --- a/media/libstagefright/colorconversion/Android.mk +++ b/media/libstagefright/colorconversion/Android.mk @@ -6,7 +6,8 @@ LOCAL_SRC_FILES:= \ 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 @@ LOCAL_SHARED_LIBRARIES := \ 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 a6dbf6912ee1..507fa5adbe12 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)); + + GraphicBufferMapper &mapper = GraphicBufferMapper::get(); + + 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); + } - mConverter.convert( - mDecodedWidth, mDecodedHeight, - data, 0, dst, 2 * mDecodedWidth); + CHECK_EQ(0, mapper.unlock(buf->handle)); - mISurface->postBuffer(offset); - mIndex = 1 - mIndex; + 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 55efd41c2ce5..2542e4ecc209 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 @@ struct ARTSPController : public MediaExtractor { 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 55e2c3651a9e..f34eb45615b5 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -76,6 +76,7 @@ struct AwesomePlayer { 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 @@ private: wp<MediaPlayerBase> mListener; sp<ISurface> mISurface; + sp<Surface> mSurface; sp<MediaPlayerBase::AudioSink> mAudioSink; SystemTimeSource mSystemTimeSource; @@ -219,6 +221,7 @@ private: 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 9eed089ce9d4..8d5805693d58 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 @@ public: 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 6de761f06fe9..88b96059f83f 100644 --- a/media/libstagefright/omx/OMX.cpp +++ b/media/libstagefright/omx/OMX.cpp @@ -495,12 +495,17 @@ sp<IOMXRenderer> OMX::createRenderer( } 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 195323ed025e..ceae3a676ea3 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; + + mHandler->connect(msg); + + while (mState == CONNECTING) { + mCondition.wait(mLock); + } + + if (mState != CONNECTED) { + mHandler.clear(); + } - return OK; + 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 @@ sp<MetaData> ARTSPController::getTrackMetaData( 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 3e75ffe2e1cd..b2419bf14a76 100644 --- a/media/libstagefright/rtsp/MyHandler.h +++ b/media/libstagefright/rtsp/MyHandler.h @@ -45,18 +45,21 @@ struct MyHandler : public AHandler { 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 @@ struct MyHandler : public AHandler { 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 @@ struct MyHandler : public AHandler { case 'quit': { + if (mDoneMsg != NULL) { + mDoneMsg->setInt32("result", UNKNOWN_ERROR); + mDoneMsg->post(); + mDoneMsg = NULL; + } break; } @@ -380,6 +389,8 @@ private: }; 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 b3cc8b6825d1..53308be08df1 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 @@ class Player: public MediaPlayerBase } 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 bd2b27af7f18..cc35a3adf4ae 100644 --- a/native/android/Android.mk +++ b/native/android/Android.mk @@ -12,7 +12,8 @@ LOCAL_SRC_FILES:= \ looper.cpp \ native_activity.cpp \ native_window.cpp \ - sensor.cpp + sensor.cpp \ + storage_manager.cpp LOCAL_SHARED_LIBRARIES := \ libcutils \ @@ -23,6 +24,9 @@ LOCAL_SHARED_LIBRARIES := \ 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 000000000000..6dbe7463dd5e --- /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 000000000000..bbed8a4e2f49 --- /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 Binary files differindex b5d36cc22821..77162c87ab93 100644 --- a/packages/SystemUI/res/drawable-mdpi/battery_0.png +++ b/packages/SystemUI/res/drawable-mdpi/battery_0.png diff --git a/packages/SystemUI/res/drawable-mdpi/battery_100.png b/packages/SystemUI/res/drawable-mdpi/battery_100.png Binary files differindex 75cc4091b173..588a74b16eef 100644 --- a/packages/SystemUI/res/drawable-mdpi/battery_100.png +++ b/packages/SystemUI/res/drawable-mdpi/battery_100.png diff --git a/packages/SystemUI/res/drawable-mdpi/battery_20.png b/packages/SystemUI/res/drawable-mdpi/battery_20.png Binary files differdeleted file mode 100644 index c0d003039fde..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/battery_20.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/battery_25.png b/packages/SystemUI/res/drawable-mdpi/battery_25.png Binary files differnew file mode 100644 index 000000000000..b11570b2ff2d --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/battery_25.png diff --git a/packages/SystemUI/res/drawable-mdpi/battery_40.png b/packages/SystemUI/res/drawable-mdpi/battery_40.png Binary files differdeleted file mode 100644 index e301c08f0a9d..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/battery_40.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/battery_50.png b/packages/SystemUI/res/drawable-mdpi/battery_50.png Binary files differnew file mode 100644 index 000000000000..94d7eca5535e --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/battery_50.png diff --git a/packages/SystemUI/res/drawable-mdpi/battery_60.png b/packages/SystemUI/res/drawable-mdpi/battery_60.png Binary files differdeleted file mode 100644 index 0fde1fa2782e..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/battery_60.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/battery_75.png b/packages/SystemUI/res/drawable-mdpi/battery_75.png Binary files differnew file mode 100644 index 000000000000..3cb35910bdc2 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/battery_75.png diff --git a/packages/SystemUI/res/drawable-mdpi/battery_80.png b/packages/SystemUI/res/drawable-mdpi/battery_80.png Binary files differdeleted file mode 100644 index 15c4e1c31bee..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/battery_80.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/signal_0.png b/packages/SystemUI/res/drawable-mdpi/signal_0.png Binary files differindex 6533677b04d4..cf436ad2adcb 100644 --- a/packages/SystemUI/res/drawable-mdpi/signal_0.png +++ b/packages/SystemUI/res/drawable-mdpi/signal_0.png diff --git a/packages/SystemUI/res/drawable-mdpi/signal_100.png b/packages/SystemUI/res/drawable-mdpi/signal_100.png Binary files differindex e8976a26d06c..0011a1b1c1d4 100644 --- a/packages/SystemUI/res/drawable-mdpi/signal_100.png +++ b/packages/SystemUI/res/drawable-mdpi/signal_100.png diff --git a/packages/SystemUI/res/drawable-mdpi/signal_20.png b/packages/SystemUI/res/drawable-mdpi/signal_20.png Binary files differdeleted file mode 100644 index 651e2a96d967..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/signal_20.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/signal_25.png b/packages/SystemUI/res/drawable-mdpi/signal_25.png Binary files differnew file mode 100644 index 000000000000..69c643f59de8 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/signal_25.png diff --git a/packages/SystemUI/res/drawable-mdpi/signal_40.png b/packages/SystemUI/res/drawable-mdpi/signal_40.png Binary files differdeleted file mode 100644 index 6ba7906db72f..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/signal_40.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/signal_50.png b/packages/SystemUI/res/drawable-mdpi/signal_50.png Binary files differnew file mode 100644 index 000000000000..c8acd72d77f5 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/signal_50.png diff --git a/packages/SystemUI/res/drawable-mdpi/signal_60.png b/packages/SystemUI/res/drawable-mdpi/signal_60.png Binary files differdeleted file mode 100644 index 6d2e8128fe7e..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/signal_60.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/signal_75.png b/packages/SystemUI/res/drawable-mdpi/signal_75.png Binary files differnew file mode 100644 index 000000000000..9650dfa20468 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/signal_75.png diff --git a/packages/SystemUI/res/drawable-mdpi/signal_80.png b/packages/SystemUI/res/drawable-mdpi/signal_80.png Binary files differdeleted file mode 100644 index a1526234a785..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/signal_80.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_back_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_back_default.png Binary files differindex dd64746a3d4f..5c578022412a 100644 --- a/packages/SystemUI/res/drawable-mdpi/status_bar_back_default.png +++ b/packages/SystemUI/res/drawable-mdpi/status_bar_back_default.png diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.png Binary files differindex 66a3677b548e..5c578022412a 100644 --- a/packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.png +++ b/packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.png diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png Binary files differindex 4d197179368d..b2a94b649b58 100644 --- a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png +++ b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png Binary files differindex 830cbd521858..b2a94b649b58 100644 --- a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png +++ b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_home_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_home_default.png Binary files differindex b12921078d12..f219dedc85f0 100644 --- a/packages/SystemUI/res/drawable-mdpi/status_bar_home_default.png +++ b/packages/SystemUI/res/drawable-mdpi/status_bar_home_default.png diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.png Binary files differindex dcb244764a2c..f219dedc85f0 100644 --- a/packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.png +++ b/packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.png 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 Binary files differindex 07d00cb30058..502acce57ada 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 diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_recent_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_default.png Binary files differnew file mode 100644 index 000000000000..4dd8dc72597b --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_default.png diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.png Binary files differnew file mode 100644 index 000000000000..4dd8dc72597b --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.png diff --git a/packages/SystemUI/res/drawable/battery.xml b/packages/SystemUI/res/drawable/battery.xml index c2294d1072ce..f4a720d17a1f 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 2fd0c6d3b764..c9b77ddda927 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 8b4f56b2962e..5aa211af6729 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 2dabf72e1e2a..ca9a484cd2ad 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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { /* 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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } 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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } 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 b3e0ee6ebdef..07b5a37e4af8 100644 --- a/services/camera/libcameraservice/CameraHardwareStub.cpp +++ b/services/camera/libcameraservice/CameraHardwareStub.cpp @@ -101,9 +101,9 @@ CameraHardwareStub::~CameraHardwareStub() 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 d3427ba4b7e1..9b66a76ba831 100644 --- a/services/camera/libcameraservice/CameraHardwareStub.h +++ b/services/camera/libcameraservice/CameraHardwareStub.h @@ -29,7 +29,7 @@ namespace android { 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 3b3904ab1be7..c6a99094024d 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -145,7 +145,12 @@ sp<ICamera> CameraService::connect( 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 @@ void CameraService::playSound(sound_kind kind) { // ---------------------------------------------------------------------------- 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 @@ CameraService::Client::~Client() { 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 @@ void CameraService::Client::disconnect() { 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 @@ void CameraService::Client::disconnect() { // ---------------------------------------------------------------------------- -// 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 @@ status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) { // 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 @@ status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) { // 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 @@ status_t CameraService::Client::startCameraMode(camera_mode mode) { 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 @@ status_t CameraService::Client::startPreviewMode() { 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 @@ void CameraService::Client::stopPreview() { 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::dataCallbackTimestamp(nsecs_t timestamp, 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 @@ void CameraService::Client::handleShutter(image_rect_type *size) { HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0, mHardware->getRawHeap()); - mSurface->registerBuffers(buffers); IPCThreadState::self()->flushCommands(); } @@ -1037,12 +1010,6 @@ void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) { 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 @@ void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) { 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 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) { 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 77ccf41000d0..7ed192e54e78 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -79,6 +79,12 @@ private: 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 @@ private: 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 @@ private: 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 @@ private: // 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 4da0bac4ea52..bd2a0eaa6b1f 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -943,7 +943,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { } 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 @@ public class ConnectivityService extends IConnectivityManager.Stub { 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 @@ public class ConnectivityService extends IConnectivityManager.Stub { } 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 9f8557fa4a9a..8b023559ec64 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -357,7 +357,7 @@ public class WifiService extends IWifiManager.Stub { */ public boolean pingSupplicant() { enforceAccessPermission(); - return mWifiStateMachine.pingSupplicant(); + return mWifiStateMachine.syncPingSupplicant(); } /** @@ -436,7 +436,7 @@ public class WifiService extends IWifiManager.Stub { */ public int getWifiEnabledState() { enforceAccessPermission(); - return mWifiStateMachine.getWifiState(); + return mWifiStateMachine.syncGetWifiState(); } /** @@ -481,7 +481,7 @@ public class WifiService extends IWifiManager.Stub { */ public int getWifiApEnabledState() { enforceAccessPermission(); - return mWifiStateMachine.getWifiApState(); + return mWifiStateMachine.syncGetWifiApState(); } /** @@ -555,7 +555,7 @@ public class WifiService extends IWifiManager.Stub { */ public List<WifiConfiguration> getConfiguredNetworks() { enforceAccessPermission(); - return mWifiStateMachine.getConfiguredNetworks(); + return mWifiStateMachine.syncGetConfiguredNetworks(); } /** @@ -565,7 +565,7 @@ public class WifiService extends IWifiManager.Stub { */ public int addOrUpdateNetwork(WifiConfiguration config) { enforceChangePermission(); - return mWifiStateMachine.addOrUpdateNetwork(config); + return mWifiStateMachine.syncAddOrUpdateNetwork(config); } /** @@ -576,7 +576,7 @@ public class WifiService extends IWifiManager.Stub { */ public boolean removeNetwork(int netId) { enforceChangePermission(); - return mWifiStateMachine.removeNetwork(netId); + return mWifiStateMachine.syncRemoveNetwork(netId); } /** @@ -588,7 +588,7 @@ public class WifiService extends IWifiManager.Stub { */ public boolean enableNetwork(int netId, boolean disableOthers) { enforceChangePermission(); - return mWifiStateMachine.enableNetwork(netId, disableOthers); + return mWifiStateMachine.syncEnableNetwork(netId, disableOthers); } /** @@ -599,7 +599,7 @@ public class WifiService extends IWifiManager.Stub { */ public boolean disableNetwork(int netId) { enforceChangePermission(); - return mWifiStateMachine.disableNetwork(netId); + return mWifiStateMachine.syncDisableNetwork(netId); } /** @@ -612,7 +612,7 @@ public class WifiService extends IWifiManager.Stub { * 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 class WifiService extends IWifiManager.Stub { */ public List<ScanResult> getScanResults() { enforceAccessPermission(); - return mWifiStateMachine.getScanResultsList(); + return mWifiStateMachine.syncGetScanResultsList(); } /** @@ -634,7 +634,7 @@ public class WifiService extends IWifiManager.Stub { public boolean saveConfiguration() { boolean result = true; enforceChangePermission(); - return mWifiStateMachine.saveConfig(); + return mWifiStateMachine.syncSaveConfig(); } /** @@ -723,7 +723,7 @@ public class WifiService extends IWifiManager.Stub { */ public DhcpInfo getDhcpInfo() { enforceAccessPermission(); - return mWifiStateMachine.getDhcpInfo(); + return mWifiStateMachine.syncGetDhcpInfo(); } /** @@ -823,7 +823,7 @@ public class WifiService extends IWifiManager.Stub { * 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 @@ public class WifiService extends IWifiManager.Stub { + ", 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 @@ public class WifiService extends IWifiManager.Stub { 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 @@ public class WifiService extends IWifiManager.Stub { 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 57f93c446380..d5750c6add2e 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.Bundle; 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.IWindowSession; 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.Animation; 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub Surface.closeTransaction(); + if (mWatermark != null) { + mWatermark.drawIfNeeded(); + } + if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, "With display frozen, orientationChangeComplete=" + orientationChangeComplete); @@ -10067,12 +10061,17 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub } class Watermark { + 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; + Surface mSurface; - int mWidth; - int mHeight; - int mXPercent; - int mYPercent; + int mLastDW; + int mLastDH; + boolean mDrawNeeded; - Watermark(SurfaceSession session, String text) { + 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", + if (false) { + Log.i(TAG, "*********************** WATERMARK"); + for (int i=0; i<tokens.length; i++) { + Log.i(TAG, " TOKEN #" + i + ": " + tokens[i]); + } + } + + mTokens = tokens; + + 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("ro.watermark.shadow.dy", + int shadowDy = getPropertyInt(tokens, 9, TypedValue.COMPLEX_UNIT_PX, 0, dm); - int shadowColor = getPropertyInt("ro.watermark.shadow.color", - TypedValue.COMPLEX_UNIT_PX, 0xff000000, dm); - 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)); - - FontMetricsInt fm = paint.getFontMetricsInt(); - mHeight = fm.descent - fm.ascent + 20; - mWidth = (int)paint.measureText(text) + 20; + 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 63746e7b7c0d..56159b5f1c5c 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -4100,16 +4100,23 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } if (pi == null) { Slog.w(TAG, "No content provider found for: " + name); - return; + return -1; } int targetUid; @@ -4143,10 +4150,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - // 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen r.foregroundNoti = null; // Clear start entries. - r.deliveredStarts.clear(); + r.clearDeliveredStartsLocked(); r.pendingStarts.clear(); if (r.app != null) { @@ -8662,6 +8700,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen ? 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 79756a7af272..80a41b7fb31b 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.graphics.Bitmap; 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 @@ import java.util.HashSet; /** * 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 @@ class ActivityRecord extends IApplicationToken.Stub { * 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 @@ class ActivityRecord extends IApplicationToken.Stub { 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 @@ class ActivityRecord extends IApplicationToken.Stub { 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 de7b15cc0091..a5f7e96866fe 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -2033,16 +2033,6 @@ public class ActivityStack { } } - 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 @@ public class ActivityStack { 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 @@ public class ActivityStack { 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 @@ public class ActivityStack { // 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 @@ public class ActivityStack { 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 @@ public class ActivityStack { 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 @@ public class ActivityStack { 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 c3f0b3e8de58..bac21b1cd87a 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.Bundle; 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 @@ class BroadcastRecord extends Binder { 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 @@ class BroadcastRecord extends Binder { 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 ab5a78d0d559..255fbe38993a 100644 --- a/services/java/com/android/server/am/ServiceRecord.java +++ b/services/java/com/android/server/am/ServiceRecord.java @@ -36,6 +36,7 @@ import android.util.TimeUtils; 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 @@ import java.util.List; * 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 @@ class ServiceRecord extends Binder { 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 @@ class ServiceRecord extends Binder { 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 @@ class ServiceRecord extends Binder { 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 @@ class ServiceRecord extends Binder { } } + 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 81450c5758f8..93c59cc1dd99 100644 --- a/services/java/com/android/server/am/UriPermission.java +++ b/services/java/com/android/server/am/UriPermission.java @@ -22,13 +22,20 @@ import android.net.Uri; 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 @@ class UriPermission { 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 @@ class UriPermission { 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 949b8743ac43..53ce5c05c189 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.INetworkManagementEventObserver; 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 @@ public class Tethering extends INetworkManagementEventObserver.Stub { 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 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } } + 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 db3f536b33e5..d33558bb6f3d 100644 --- a/services/java/com/android/server/sip/SipSessionGroup.java +++ b/services/java/com/android/server/sip/SipSessionGroup.java @@ -381,14 +381,29 @@ class SipSessionGroup implements SipListener { : 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 @@ class SipSessionGroup implements SipListener { } 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 79772edec355..e4825d02a96e 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -22,7 +22,7 @@ LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" 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 d25789726668..a78d9b914cb2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -165,7 +165,7 @@ void SurfaceFlinger::bootFinished() { 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 @@ status_t SurfaceFlinger::readyToRun() 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 @@ status_t SurfaceFlinger::readyToRun() // 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 @@ status_t SurfaceFlinger::readyToRun() // start boot animation property_set("ctl.start", "bootanim"); - + return NO_ERROR; } @@ -662,7 +662,7 @@ void SurfaceFlinger::computeVisibleRegions( // 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 @@ void SurfaceFlinger::handleRepaint() 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 @@ void SurfaceFlinger::closeGlobalTransaction() 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 @@ status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags) 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 @@ sp<ISurface> SurfaceFlinger::createSurface(const sp<Client>& client, int pid, 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 @@ sp<ISurface> SurfaceFlinger::createSurface(const sp<Client>& client, int pid, 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 @@ status_t SurfaceFlinger::removeSurface(const sp<Client>& client, SurfaceID sid) /* * 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::removeSurface(const sp<Client>& client, SurfaceID sid) 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 @@ status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer) 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 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) } 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 @@ ssize_t UserClient::getTokenForSurface(const sp<ISurface>& sur) const { 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 92bed8de81eb..2370add7377e 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -177,7 +177,7 @@ public class TelephonyManager { /** * 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 8e085928154e..980affa75cf4 100644 --- a/telephony/java/com/android/internal/telephony/CallManager.java +++ b/telephony/java/com/android/internal/telephony/CallManager.java @@ -322,7 +322,9 @@ public final class CallManager { } 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 9e17eb1a58f1..f1a710744fcb 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.Config; 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 @@ public abstract class SMSDispatcher extends Handler { 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 @@ public abstract class SMSDispatcher extends Handler { "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 @@ public abstract class SMSDispatcher extends Handler { */ 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 @@ public abstract class SMSDispatcher extends Handler { mSTrackers.add(tracker); sendMessageDelayed ( obtainMessage(EVENT_ALERT_TIMEOUT, d), - DEFAULT_SMS_TIMOUEOUT); + DEFAULT_SMS_TIMEOUT); } protected String getAppNameByIntent(PendingIntent intent) { @@ -932,7 +922,7 @@ public abstract class SMSDispatcher extends Handler { } /** - * 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 @@ public abstract class SMSDispatcher extends Handler { } }; - 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); - } + 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); } - - }; + } + }; } diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index 0c3c534cad0e..b39556aa54b2 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 @@ public class CDMAPhone extends PhoneBase { 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 1b08aeddd670..53d0f207e074 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.database.SQLException; 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 @@ import java.util.HashMap; 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 @@ final class CdmaSMSDispatcher extends SMSDispatcher { 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 @@ final class CdmaSMSDispatcher extends SMSDispatcher { 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 aa16fa30633b..fe7a5cb4a456 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 @@ public final class GsmMmiCode extends Handler implements MmiCode { //***** 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 @@ public final class GsmMmiCode extends Handler implements MmiCode { } /** - * 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 f09ff06ca45d..ed7066bc5840 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.telephony.ServiceState; 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 @@ final class GsmSMSDispatcher extends SMSDispatcher { 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 @@ final class GsmSMSDispatcher extends SMSDispatcher { 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 ad05b82f2746..f5d84eb62d97 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 @@ abstract class SipConnectionBase extends Connection { 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 81dfaeb506e6..9a45d3ae347d 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 class SipPhone extends SipPhoneBase { } public String getPhoneName() { - return mProfile.getProfileName(); + return "SIP:" + getUriString(mProfile); } public String getSipUri() { @@ -225,21 +225,25 @@ public class SipPhone extends SipPhoneBase { } 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 class SipPhone extends SipPhoneBase { } 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 @@ public class SipPhone extends SipPhoneBase { 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 class SipPhone extends SipPhoneBase { } public void setMute(boolean muted) { - foregroundCall.setMute(muted); + synchronized (SipPhone.class) { + foregroundCall.setMute(muted); + } } public boolean getMute() { @@ -413,18 +423,20 @@ public class SipPhone extends SipPhoneBase { @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 @@ public class SipPhone extends SipPhoneBase { } 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 @@ public class SipPhone extends SipPhoneBase { } 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 @@ public class SipPhone extends SipPhoneBase { 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 @@ public class SipPhone extends SipPhoneBase { } void hold() throws CallStateException { + setState(Call.State.HOLDING); try { mSipAudioCall.holdCall(); } catch (SipException e) { @@ -683,7 +705,9 @@ public class SipPhone extends SipPhoneBase { } } - 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 @@ public class SipPhone extends SipPhoneBase { } } - 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 @@ public class SipPhone extends SipPhoneBase { @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 721b8af8052c..1d33be9e90a0 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 @@ abstract class SipPhoneBase extends PhoneBase { 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 03b7e2675674..c1512514dbcb 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 9f580a380bc1..4cff3de22d37 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java @@ -95,6 +95,7 @@ public class FileFilter { 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 c40af80d744e..abccf9be9d0c 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -338,6 +338,7 @@ enum { SMALL_SCREEN_ATTR = 0x01010284, NORMAL_SCREEN_ATTR = 0x01010285, LARGE_SCREEN_ATTR = 0x01010286, + XLARGE_SCREEN_ATTR = 0x010102bf, REQUIRED_ATTR = 0x0101028e, }; @@ -572,6 +573,7 @@ int doDump(Bundle* bundle) int smallScreen = 1; int normalScreen = 1; int largeScreen = 1; + int xlargeScreen = 1; String8 pkg; String8 activityName; String8 activityLabel; @@ -754,6 +756,8 @@ int doDump(Bundle* bundle) 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 @@ int doDump(Bundle* bundle) 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 f4be839da72b..3cdd11489d7e 100644 --- a/voip/java/android/net/sip/SipAudioCall.java +++ b/voip/java/android/net/sip/SipAudioCall.java @@ -244,7 +244,8 @@ public interface SipAudioCall { * 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 @@ public interface SipAudioCall { 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 7161309ec46d..b8ac6d73522a 100644 --- a/voip/java/android/net/sip/SipAudioCallImpl.java +++ b/voip/java/android/net/sip/SipAudioCallImpl.java @@ -70,7 +70,8 @@ public class SipAudioCallImpl extends SipSessionAdapter 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 class SipAudioCallImpl extends SipSessionAdapter } 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 @@ public class SipAudioCallImpl extends SipSessionAdapter // 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 @@ public class SipAudioCallImpl extends SipSessionAdapter 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 @@ public class SipAudioCallImpl extends SipSessionAdapter .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 @@ public class SipAudioCallImpl extends SipSessionAdapter 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 a364355f542a..3bd85aaffffa 100644 --- a/voip/jni/rtp/Android.mk +++ b/voip/jni/rtp/Android.mk @@ -32,10 +32,11 @@ LOCAL_SHARED_LIBRARIES := \ 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 08a8d1c6d524..b5a4e22599fc 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 @@ private: int mDeviceSocket; AudioTrack mTrack; AudioRecord mRecord; + + SpeexEchoState *mEchoState; bool networkLoop(); bool deviceLoop(); @@ -506,6 +510,7 @@ AudioGroup::AudioGroup() mEventQueue = -1; mDtmfEvent = -1; mDeviceSocket = -1; + mEchoState = NULL; mNetworkThread = new NetworkThread(this); mDeviceThread = new DeviceThread(this); } @@ -518,6 +523,9 @@ AudioGroup::~AudioGroup() 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 @@ bool AudioGroup::set(int sampleRate, int sampleCount) } 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 @@ bool AudioGroup::set(int sampleRate, int sampleCount) } 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 @@ bool AudioGroup::set(int sampleRate, int sampleCount) // 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 @@ bool AudioGroup::setMode(int mode) if (mode == MUTED) { mRecord.stop(); } else { + speex_echo_state_reset(mEchoState); mRecord.start(); } @@ -764,38 +775,63 @@ bool AudioGroup::deviceLoop() 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"); - return false; - } - if (mMode != MUTED) { - uint32_t frameCount = mRecord.frameCount(); - AudioRecord::Buffer input; - input.frameCount = frameCount; + int16_t input[mSampleCount]; + int toWrite = mSampleCount; + int toRead = (mMode == MUTED) ? 0 : mSampleCount; + int chances = 100; - if (mRecord.obtainBuffer(&input, -1) != NO_ERROR) { - LOGE("cannot read from AudioRecord"); - return false; - } + while (--chances > 0 && (toWrite > 0 || toRead > 0)) { + if (toWrite > 0) { + AudioTrack::Buffer buffer; + buffer.frameCount = toWrite; - if (input.frameCount < (uint32_t)mSampleCount) { - input.frameCount = 0; - } 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); + 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 (input.frameCount < frameCount) { - input.frameCount = mSampleCount; + } + + 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; } } + } - mRecord.releaseBuffer(&input); + if (!chances) { + LOGE("device loop timeout"); + return false; } + if (mMode != MUTED) { + if (mMode == NORMAL) { + send(mDeviceSocket, input, sizeof(input), MSG_DONTWAIT); + } else { + int16_t result[mSampleCount]; + speex_echo_cancellation(mEchoState, input, output, result); + send(mDeviceSocket, result, sizeof(result), MSG_DONTWAIT); + } + } return true; } diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 01bc919281e8..559be85aafe8 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -432,6 +432,38 @@ public class WifiConfiguration implements Parcelable { 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 19c4eb0d838d..5734953c90c7 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -79,6 +79,7 @@ import java.net.SocketException; 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { /* 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { /** * TODO: doc */ - public boolean pingSupplicant() { + public boolean syncPingSupplicant() { return sendSyncMessage(CMD_PING_SUPPLICANT).boolValue; } @@ -535,14 +529,14 @@ public class WifiStateMachine extends HierarchicalStateMachine { /** * 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { /** * 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { * @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 @@ public class WifiStateMachine extends HierarchicalStateMachine { /** * TODO: doc */ - public List<ScanResult> getScanResultsList() { + public List<ScanResult> syncGetScanResultsList() { return mScanResults; } @@ -665,12 +659,19 @@ public class WifiStateMachine extends HierarchicalStateMachine { * * @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 @@ public class WifiStateMachine extends HierarchicalStateMachine { * * @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 @@ public class WifiStateMachine extends HierarchicalStateMachine { * @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 @@ public class WifiStateMachine extends HierarchicalStateMachine { * @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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { * * @return RSSI value, -1 on failure */ - public int getRssi() { + public int syncGetRssi() { return sendSyncMessage(CMD_GET_RSSI).intValue; } @@ -780,7 +764,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { * * @return RSSI value, -1 on failure */ - public int getRssiApprox() { + public int syncGetRssiApprox() { return sendSyncMessage(CMD_GET_RSSI_APPROX).intValue; } @@ -789,7 +773,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { * * @return link speed, -1 on failure */ - public int getLinkSpeed() { + public int syncGetLinkSpeed() { return sendSyncMessage(CMD_GET_LINK_SPEED).intValue; } @@ -798,7 +782,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { * * @return MAC address, null on failure */ - public String getMacAddress() { + public String syncGetMacAddress() { return sendSyncMessage(CMD_GET_MAC_ADDR).stringValue; } @@ -895,7 +879,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { * * TODO: deprecate this */ - public boolean saveConfig() { + public boolean syncSaveConfig() { return sendSyncMessage(CMD_SAVE_CONFIG).boolValue; } @@ -915,7 +899,6 @@ public class WifiStateMachine extends HierarchicalStateMachine { int intValue; String stringValue; Object objValue; - List<WifiConfiguration> configList; } class SyncParams { @@ -931,12 +914,10 @@ public class WifiStateMachine extends HierarchicalStateMachine { } /** - * 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { // 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { } 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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; + } + readNetworkVariables(config); + if (config.priority > mLastPriority) { + mLastPriority = config.priority; + } + mConfiguredNetworks.add(config); } - 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { mWifiInfo.setMacAddress(WifiNative.getMacAddressCommand()); + updateConfigAndSendChangeBroadcast(); + //TODO: initialize and fix multicast filtering //mWM.initializeMulticastFiltering(); @@ -2521,48 +2504,33 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { case CMD_CLEAR_BLACKLIST: WifiNative.clearBlacklistCommand(); break; - case CMD_GET_NETWORK_CONFIG: + case CMD_SAVE_CONFIG: syncParams = (SyncParams) message.obj; - syncParams.mSyncReturn.configList = getConfiguredNetworksNative(); + syncParams.mSyncReturn.boolValue = WifiNative.saveConfigCommand(); 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(); - } // Inform the backup manager about a data change IBackupManager ibm = IBackupManager.Stub.asInterface( ServiceManager.getService(Context.BACKUP_SERVICE)); @@ -2596,11 +2554,6 @@ public class WifiStateMachine extends HierarchicalStateMachine { } } 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { } // 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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 @@ public class WifiStateMachine extends HierarchicalStateMachine { WifiNative.disableNetworkCommand(mWifiInfo.getNetworkId()); mPasswordKeyMayBeIncorrect = false; sendSupplicantStateChangedBroadcast(stateChangeResult, true); - sendSupplicantConfigChangedBroadcast(); + updateConfigAndSendChangeBroadcast(); } else { sendSupplicantStateChangedBroadcast(stateChangeResult, false); @@ -3563,7 +3516,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { } if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) { WifiNative.disableNetworkCommand(stateChangeResult.networkId); - sendSupplicantConfigChangedBroadcast(); + updateConfigAndSendChangeBroadcast(); mLoopDetectCount = 0; } |