summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabase.java148
-rw-r--r--core/java/android/net/DhcpInfoInternal.java22
-rw-r--r--core/java/android/net/LinkProperties.java56
-rw-r--r--core/java/android/util/LruCache.java19
-rw-r--r--core/java/android/view/VolumePanel.java7
-rw-r--r--core/java/android/webkit/WebTextView.java58
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java2
-rw-r--r--docs/html/guide/guide_toc.cs8
-rw-r--r--docs/html/guide/topics/graphics/animation.jd1342
-rw-r--r--docs/html/guide/topics/graphics/renderscript.jd710
-rw-r--r--docs/html/guide/topics/graphics/view-animation.jd190
-rw-r--r--docs/html/guide/topics/media/index.jd245
-rw-r--r--docs/html/images/animation/animation-linear.pngbin0 -> 35996 bytes
-rw-r--r--docs/html/images/animation/animation-nonlinear.pngbin0 -> 42162 bytes
-rw-r--r--docs/html/images/animation/valueanimator.pngbin0 -> 42031 bytes
-rwxr-xr-xmedia/jni/mediaeditor/VideoEditorMain.cpp83
-rw-r--r--services/java/com/android/server/ConnectivityService.java8
-rw-r--r--wifi/java/android/net/wifi/WifiConfigStore.java34
18 files changed, 2090 insertions, 842 deletions
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 4605ea02ecd1..085c26b74880 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -276,17 +276,11 @@ public class SQLiteDatabase extends SQLiteClosable {
* invoked.
*
* this cache's max size is settable by calling the method
- * (@link #setMaxSqlCacheSize(int)}).
- */
- // guarded by itself
- /* package */ final LruCache<String, SQLiteCompiledSql> mCompiledQueries =
- new LruCache<String, SQLiteCompiledSql>(DEFAULT_SQL_CACHE_SIZE) {
- @Override
- protected void entryEvicted(String key, SQLiteCompiledSql value) {
- verifyLockOwner();
- value.releaseIfNotInUse();
- }
- };
+ * (@link #setMaxSqlCacheSize(int)}.
+ */
+ // guarded by this
+ private LruCache<String, SQLiteCompiledSql> mCompiledQueries;
+
/**
* absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}
* size of each prepared-statement is between 1K - 6K, depending on the complexity of the
@@ -1979,6 +1973,7 @@ public class SQLiteDatabase extends SQLiteClosable {
if (path == null) {
throw new IllegalArgumentException("path should not be null");
}
+ setMaxSqlCacheSize(DEFAULT_SQL_CACHE_SIZE);
mFlags = flags;
mPath = path;
mSlowQueryThreshold = SystemProperties.getInt(LOG_SLOW_QUERIES_PROPERTY, -1);
@@ -1991,7 +1986,7 @@ public class SQLiteDatabase extends SQLiteClosable {
mConnectionNum = connectionNum;
/* sqlite soft heap limit http://www.sqlite.org/c3ref/soft_heap_limit64.html
* set it to 4 times the default cursor window size.
- * TODO what is an appropriate value, considring the WAL feature which could burn
+ * TODO what is an appropriate value, considering the WAL feature which could burn
* a lot of memory with many connections to the database. needs testing to figure out
* optimal value for this.
*/
@@ -2145,59 +2140,55 @@ public class SQLiteDatabase extends SQLiteClosable {
* the new {@link SQLiteCompiledSql} object is NOT inserted into the cache (i.e.,the current
* mapping is NOT replaced with the new mapping).
*/
- /* package */ void addToCompiledQueries(String sql, SQLiteCompiledSql compiledStatement) {
- synchronized(mCompiledQueries) {
- // don't insert the new mapping if a mapping already exists
- if (mCompiledQueries.get(sql) != null) {
- return;
- }
+ /* package */ synchronized void addToCompiledQueries(
+ String sql, SQLiteCompiledSql compiledStatement) {
+ // don't insert the new mapping if a mapping already exists
+ if (mCompiledQueries.get(sql) != null) {
+ return;
+ }
- int maxCacheSz = (mConnectionNum == 0) ? mCompiledQueries.maxSize() :
- mParentConnObj.mCompiledQueries.maxSize();
-
- if (SQLiteDebug.DEBUG_SQL_CACHE) {
- boolean printWarning = (mConnectionNum == 0)
- ? (!mCacheFullWarning && mCompiledQueries.size() == maxCacheSz)
- : (!mParentConnObj.mCacheFullWarning &&
- mParentConnObj.mCompiledQueries.size() == maxCacheSz);
- if (printWarning) {
- /*
- * cache size of {@link #mMaxSqlCacheSize} is not enough for this app.
- * log a warning.
- * chances are it is NOT using ? for bindargs - or cachesize is too small.
- */
- Log.w(TAG, "Reached MAX size for compiled-sql statement cache for database " +
- getPath() + ". Use setMaxSqlCacheSize() to increase cachesize. ");
- mCacheFullWarning = true;
- Log.d(TAG, "Here are the SQL statements in Cache of database: " + mPath);
- for (String s : mCompiledQueries.snapshot().keySet()) {
- Log.d(TAG, "Sql statement in Cache: " + s);
- }
+ int maxCacheSz = (mConnectionNum == 0) ? mCompiledQueries.maxSize() :
+ mParentConnObj.mCompiledQueries.maxSize();
+
+ if (SQLiteDebug.DEBUG_SQL_CACHE) {
+ boolean printWarning = (mConnectionNum == 0)
+ ? (!mCacheFullWarning && mCompiledQueries.size() == maxCacheSz)
+ : (!mParentConnObj.mCacheFullWarning &&
+ mParentConnObj.mCompiledQueries.size() == maxCacheSz);
+ if (printWarning) {
+ /*
+ * cache size is not enough for this app. log a warning.
+ * chances are it is NOT using ? for bindargs - or cachesize is too small.
+ */
+ Log.w(TAG, "Reached MAX size for compiled-sql statement cache for database " +
+ getPath() + ". Use setMaxSqlCacheSize() to increase cachesize. ");
+ mCacheFullWarning = true;
+ Log.d(TAG, "Here are the SQL statements in Cache of database: " + mPath);
+ for (String s : mCompiledQueries.snapshot().keySet()) {
+ Log.d(TAG, "Sql statement in Cache: " + s);
}
}
- /* add the given SQLiteCompiledSql compiledStatement to cache.
- * no need to worry about the cache size - because {@link #mCompiledQueries}
- * self-limits its size to {@link #mMaxSqlCacheSize}.
- */
- mCompiledQueries.put(sql, compiledStatement);
}
+ /* add the given SQLiteCompiledSql compiledStatement to cache.
+ * no need to worry about the cache size - because {@link #mCompiledQueries}
+ * self-limits its size.
+ */
+ mCompiledQueries.put(sql, compiledStatement);
}
/** package-level access for testing purposes */
- /* package */ void deallocCachedSqlStatements() {
- synchronized (mCompiledQueries) {
- for (SQLiteCompiledSql compiledSql : mCompiledQueries.snapshot().values()) {
- compiledSql.releaseSqlStatement();
- }
- mCompiledQueries.evictAll();
+ /* package */ synchronized void deallocCachedSqlStatements() {
+ for (SQLiteCompiledSql compiledSql : mCompiledQueries.snapshot().values()) {
+ compiledSql.releaseSqlStatement();
}
+ mCompiledQueries.evictAll();
}
/**
* From the compiledQueries cache, returns the compiled-statement-id for the given SQL.
* Returns null, if not found in the cache.
*/
- /* package */ SQLiteCompiledSql getCompiledStatementForSql(String sql) {
+ /* package */ synchronized SQLiteCompiledSql getCompiledStatementForSql(String sql) {
return mCompiledQueries.get(sql);
}
@@ -2216,44 +2207,55 @@ public class SQLiteDatabase extends SQLiteClosable {
* the value set with previous setMaxSqlCacheSize() call.
*/
public void setMaxSqlCacheSize(int cacheSize) {
- synchronized(mCompiledQueries) {
+ synchronized (this) {
+ LruCache<String, SQLiteCompiledSql> oldCompiledQueries = mCompiledQueries;
if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) {
- throw new IllegalStateException("expected value between 0 and " + MAX_SQL_CACHE_SIZE);
- } else if (cacheSize < mCompiledQueries.maxSize()) {
- throw new IllegalStateException("cannot set cacheSize to a value less than the value " +
- "set with previous setMaxSqlCacheSize() call.");
+ throw new IllegalStateException(
+ "expected value between 0 and " + MAX_SQL_CACHE_SIZE);
+ } else if (oldCompiledQueries != null && cacheSize < oldCompiledQueries.maxSize()) {
+ throw new IllegalStateException("cannot set cacheSize to a value less than the "
+ + "value set with previous setMaxSqlCacheSize() call.");
+ }
+ mCompiledQueries = new LruCache<String, SQLiteCompiledSql>(cacheSize) {
+ @Override
+ protected void entryEvicted(String key, SQLiteCompiledSql value) {
+ verifyLockOwner();
+ value.releaseIfNotInUse();
+ }
+ };
+ if (oldCompiledQueries != null) {
+ for (Map.Entry<String, SQLiteCompiledSql> entry
+ : oldCompiledQueries.snapshot().entrySet()) {
+ mCompiledQueries.put(entry.getKey(), entry.getValue());
+ }
}
- mCompiledQueries.setMaxSize(cacheSize);
}
}
- /* package */ boolean isInStatementCache(String sql) {
- synchronized (mCompiledQueries) {
- return mCompiledQueries.get(sql) != null;
- }
+ /* package */ synchronized boolean isInStatementCache(String sql) {
+ return mCompiledQueries.get(sql) != null;
}
- /* package */ void releaseCompiledSqlObj(String sql, SQLiteCompiledSql compiledSql) {
- synchronized (mCompiledQueries) {
- if (mCompiledQueries.get(sql) == compiledSql) {
- // it is in cache - reset its inUse flag
- compiledSql.release();
- } else {
- // it is NOT in cache. finalize it.
- compiledSql.releaseSqlStatement();
- }
+ /* package */ synchronized void releaseCompiledSqlObj(
+ String sql, SQLiteCompiledSql compiledSql) {
+ if (mCompiledQueries.get(sql) == compiledSql) {
+ // it is in cache - reset its inUse flag
+ compiledSql.release();
+ } else {
+ // it is NOT in cache. finalize it.
+ compiledSql.releaseSqlStatement();
}
}
- private int getCacheHitNum() {
+ private synchronized int getCacheHitNum() {
return mCompiledQueries.hitCount();
}
- private int getCacheMissNum() {
+ private synchronized int getCacheMissNum() {
return mCompiledQueries.missCount();
}
- private int getCachesize() {
+ private synchronized int getCachesize() {
return mCompiledQueries.size();
}
diff --git a/core/java/android/net/DhcpInfoInternal.java b/core/java/android/net/DhcpInfoInternal.java
index 6e981dfea5ee..73966692d03f 100644
--- a/core/java/android/net/DhcpInfoInternal.java
+++ b/core/java/android/net/DhcpInfoInternal.java
@@ -44,12 +44,14 @@ public class DhcpInfoInternal {
}
private int convertToInt(String addr) {
- try {
- InetAddress inetAddress = NetworkUtils.numericToInetAddress(addr);
- if (inetAddress instanceof Inet4Address) {
- return NetworkUtils.inetAddressToInt(inetAddress);
- }
- } catch (IllegalArgumentException e) {}
+ if (addr != null) {
+ try {
+ InetAddress inetAddress = NetworkUtils.numericToInetAddress(addr);
+ if (inetAddress instanceof Inet4Address) {
+ return NetworkUtils.inetAddressToInt(inetAddress);
+ }
+ } catch (IllegalArgumentException e) {}
+ }
return 0;
}
@@ -80,19 +82,17 @@ public class DhcpInfoInternal {
LinkProperties p = new LinkProperties();
p.addLinkAddress(makeLinkAddress());
if (TextUtils.isEmpty(gateway) == false) {
- p.setGateway(NetworkUtils.numericToInetAddress(gateway));
- } else {
- Log.e(TAG, "makeLinkProperties with empty gateway!");
+ p.addGateway(NetworkUtils.numericToInetAddress(gateway));
}
if (TextUtils.isEmpty(dns1) == false) {
p.addDns(NetworkUtils.numericToInetAddress(dns1));
} else {
- Log.e(TAG, "makeLinkProperties with empty dns1!");
+ Log.d(TAG, "makeLinkProperties with empty dns1!");
}
if (TextUtils.isEmpty(dns2) == false) {
p.addDns(NetworkUtils.numericToInetAddress(dns2));
} else {
- Log.e(TAG, "makeLinkProperties with empty dns2!");
+ Log.d(TAG, "makeLinkProperties with empty dns2!");
}
return p;
}
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index f1545eab4686..b6e9751a520b 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -31,7 +31,24 @@ import java.util.Collections;
/**
* Describes the properties of a network link.
- * TODO - consider adding optional fields like Apn and ApnType
+ *
+ * A link represents a connection to a network.
+ * It may have multiple addresses and multiple gateways,
+ * multiple dns servers but only one http proxy.
+ *
+ * Because it's a single network, the dns's
+ * are interchangeable and don't need associating with
+ * particular addresses. The gateways similarly don't
+ * need associating with particular addresses.
+ *
+ * A dual stack interface works fine in this model:
+ * each address has it's own prefix length to describe
+ * the local network. The dns servers all return
+ * both v4 addresses and v6 addresses regardless of the
+ * address family of the server itself (rfc4213) and we
+ * don't care which is used. The gateways will be
+ * selected based on the destination address and the
+ * source address has no relavence.
* @hide
*/
public class LinkProperties implements Parcelable {
@@ -39,7 +56,7 @@ public class LinkProperties implements Parcelable {
String mIfaceName;
private Collection<LinkAddress> mLinkAddresses;
private Collection<InetAddress> mDnses;
- private InetAddress mGateway;
+ private Collection<InetAddress> mGateways;
private ProxyProperties mHttpProxy;
public LinkProperties() {
@@ -52,7 +69,7 @@ public class LinkProperties implements Parcelable {
mIfaceName = source.getInterfaceName();
mLinkAddresses = source.getLinkAddresses();
mDnses = source.getDnses();
- mGateway = source.getGateway();
+ mGateways = source.getGateways();
mHttpProxy = new ProxyProperties(source.getHttpProxy());
}
}
@@ -89,11 +106,11 @@ public class LinkProperties implements Parcelable {
return Collections.unmodifiableCollection(mDnses);
}
- public void setGateway(InetAddress gateway) {
- mGateway = gateway;
+ public void addGateway(InetAddress gateway) {
+ mGateways.add(gateway);
}
- public InetAddress getGateway() {
- return mGateway;
+ public Collection<InetAddress> getGateways() {
+ return Collections.unmodifiableCollection(mGateways);
}
public void setHttpProxy(ProxyProperties proxy) {
@@ -107,7 +124,7 @@ public class LinkProperties implements Parcelable {
mIfaceName = null;
mLinkAddresses = new ArrayList<LinkAddress>();
mDnses = new ArrayList<InetAddress>();
- mGateway = null;
+ mGateways = new ArrayList<InetAddress>();
mHttpProxy = null;
}
@@ -131,10 +148,12 @@ public class LinkProperties implements Parcelable {
for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
dns += "] ";
+ String gateways = "Gateways: [";
+ for (InetAddress gw : mGateways) gateways += gw.getHostAddress() + ",";
+ gateways += "] ";
String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
- String gateway = (mGateway == null ? "" : "Gateway: " + mGateway.getHostAddress() + " ");
- return ifaceName + linkAddresses + gateway + dns + proxy;
+ return ifaceName + linkAddresses + gateways + dns + proxy;
}
/**
@@ -152,12 +171,12 @@ public class LinkProperties implements Parcelable {
for(InetAddress d : mDnses) {
dest.writeByteArray(d.getAddress());
}
- if (mGateway != null) {
- dest.writeByte((byte)1);
- dest.writeByteArray(mGateway.getAddress());
- } else {
- dest.writeByte((byte)0);
+
+ dest.writeInt(mGateways.size());
+ for(InetAddress gw : mGateways) {
+ dest.writeByteArray(gw.getAddress());
}
+
if (mHttpProxy != null) {
dest.writeByte((byte)1);
dest.writeParcelable(mHttpProxy, flags);
@@ -192,10 +211,11 @@ public class LinkProperties implements Parcelable {
netProp.addDns(InetAddress.getByAddress(in.createByteArray()));
} catch (UnknownHostException e) { }
}
- if (in.readByte() == 1) {
+ addressCount = in.readInt();
+ for (int i=0; i<addressCount; i++) {
try {
- netProp.setGateway(InetAddress.getByAddress(in.createByteArray()));
- } catch (UnknownHostException e) {}
+ netProp.addGateway(InetAddress.getByAddress(in.createByteArray()));
+ } catch (UnknownHostException e) { }
}
if (in.readByte() == 1) {
netProp.setHttpProxy((ProxyProperties)in.readParcelable(null));
diff --git a/core/java/android/util/LruCache.java b/core/java/android/util/LruCache.java
index 6ee09cb443ad..212205087de4 100644
--- a/core/java/android/util/LruCache.java
+++ b/core/java/android/util/LruCache.java
@@ -155,25 +155,6 @@ public class LruCache<K, V> {
}
/**
- * Sets the maximum size of this cache. Decreasing the maximum size may
- * evict entries from this cache.
- *
- * @hide
- *
- * @param maxSize for caches that do not override {@link #sizeOf}, this is
- * the maximum number of entries in the cache. For all other caches,
- * this is the maximum sum of the sizes of the entries in this cache.
- */
- public synchronized final void setMaxSize(int maxSize) {
- if (maxSize <= 0) {
- throw new IllegalArgumentException("maxSize <= 0");
- }
-
- trimToSize(maxSize);
- this.maxSize = maxSize;
- }
-
- /**
* Called for entries that have reached the tail of the least recently used
* queue and are be removed. The default implementation does nothing.
*/
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index a67ce170a701..89b7aaadd2d8 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -342,11 +342,10 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
if (LOGD) Log.d(TAG, "onVolumeChanged(streamType: " + streamType + ", flags: " + flags + ")");
- if (mActiveStreamType == -1) {
- reorderSliders(streamType);
- }
-
if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
+ if (mActiveStreamType == -1) {
+ reorderSliders(streamType);
+ }
onShowVolumeChanged(streamType, flags);
}
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 6e1a6fcba4bb..492cb8024efc 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -67,7 +67,8 @@ import junit.framework.Assert;
* to overlay html textfields (and textareas) to use our standard
* text editing.
*/
-/* package */ class WebTextView extends AutoCompleteTextView {
+/* package */ class WebTextView extends AutoCompleteTextView
+ implements AdapterView.OnItemClickListener {
static final String LOGTAG = "webtextview";
@@ -558,6 +559,27 @@ import junit.framework.Assert;
mFromFocusChange = false;
}
+ // AdapterView.OnItemClickListener implementation
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (id == 0 && position == 0) {
+ // Blank out the text box while we wait for WebCore to fill the form.
+ replaceText("");
+ WebSettings settings = mWebView.getSettings();
+ if (mAutoFillProfileIsSet) {
+ // Call a webview method to tell WebCore to autofill the form.
+ mWebView.autoFillForm(mQueryId);
+ } else {
+ // There is no autofill profile setup yet and the user has
+ // elected to try and set one up. Call through to the
+ // embedder to action that.
+ mWebView.getWebChromeClient().setupAutoFill(
+ mHandler.obtainMessage(AUTOFILL_FORM));
+ }
+ }
+ }
+
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
@@ -814,33 +836,16 @@ import junit.framework.Assert;
setInputType(getInputType()
| EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE);
adapter.setTextView(this);
- }
- super.setAdapter(adapter);
- if (mAutoFillable) {
- setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- if (id == 0 && position == 0) {
- // Blank out the text box while we wait for WebCore to fill the form.
- replaceText("");
- WebSettings settings = mWebView.getSettings();
- if (mAutoFillProfileIsSet) {
- // Call a webview method to tell WebCore to autofill the form.
- mWebView.autoFillForm(mQueryId);
- } else {
- // There is no autofill profile setup yet and the user has
- // elected to try and set one up. Call through to the
- // embedder to action that.
- mWebView.getWebChromeClient().setupAutoFill(
- mHandler.obtainMessage(AUTOFILL_FORM));
- }
- }
- }
- });
+ if (mAutoFillable) {
+ setOnItemClickListener(this);
+ } else {
+ setOnItemClickListener(null);
+ }
+ showDropDown();
} else {
- setOnItemClickListener(null);
+ dismissDropDown();
}
- showDropDown();
+ super.setAdapter(adapter);
}
/**
@@ -858,6 +863,7 @@ import junit.framework.Assert;
/**
* {@inheritDoc}
*/
+ @Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv =
(TextView) super.getView(position, convertView, parent);
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index 21f1bfc29d51..1ecf10389178 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -303,7 +303,7 @@ public class AccessPointParserHelper {
if (!InetAddress.isNumeric(gwAddr)) {
throw new SAXException();
}
- mLinkProperties.setGateway(InetAddress.getByName(gwAddr));
+ mLinkProperties.addGateway(InetAddress.getByName(gwAddr));
} catch (UnknownHostException e) {
throw new SAXException();
}
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 27a4b89e24f3..2274735283c4 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -237,9 +237,15 @@
<li><a href="<?cs var:toroot ?>guide/topics/graphics/opengl.html">
<span class="en">3D with OpenGL</span>
</a></li>
+ <li><a href="<?cs var:toroot ?>guide/topics/graphics/renderscript.html">
+ <span class="en">3D with Renderscript</span>
+ </a><span class="new">new!</span></li>
<li><a href="<?cs var:toroot ?>guide/topics/graphics/animation.html">
- <span class="en">Animation</span>
+ <span class="en">Property Animation</span>
</a><span class="new">new!</span></li>
+ <li><a href="<?cs var:toroot ?>guide/topics/graphics/view-animation.html">
+ <span class="en">View Animation</span>
+ </a></li>
</ul>
</li>
<li><a href="<?cs var:toroot ?>guide/topics/media/index.html">
diff --git a/docs/html/guide/topics/graphics/animation.jd b/docs/html/guide/topics/graphics/animation.jd
index 83a4e1d30662..cd74efa4d539 100644
--- a/docs/html/guide/topics/graphics/animation.jd
+++ b/docs/html/guide/topics/graphics/animation.jd
@@ -1,40 +1,37 @@
-page.title=Animation
+page.title=Property Animation
@jd:body
- <div id="qv-wrapper">
+
+ <div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
- <li>
- <a href="#property-animation">Property Animation</a>
-
+ <li><a href="#what">What is Property Animation?</a>
<ol>
+ <li><a href="#how">How property animation works</a></li>
+ </ol>
+ </li>
+
<li><a href="#value-animator">Animating with ValueAnimator</a></li>
<li><a href="#object-animator">Animating with ObjectAnimator</a></li>
- <li><a href="#type-evaluator">Using a TypeEvaluator</a></li>
-
- <li><a href="#interpolators">Using interpolators</a></li>
+ <li><a href="#choreography">Choreographing Multiple Animations with
+ AnimatorSet</a></li>
+
+ <li><a href="#listeners">Animation Listeners</a></li>
- <li><a href="#keyframes">Specifying keyframes</a></li>
+ <li><a href="#type-evaluator">Using a TypeEvaluator</a></li>
- <li><a href="#choreography">Choreographing multiple animations with AnimatorSet</a></li>
+ <li><a href="#interpolators">Using Interpolators</a></li>
- <li><a href="#declaring-xml">Declaring animations in XML</a></li>
- </ol>
- </li>
+ <li><a href="#keyframes">Specifying Keyframes</a></li>
+ <li><a href="#layout">Animating Layout Changes to ViewGroups</a></li>
- <li>
- <a href="#view-animation">View Animation</a>
+ <li><a href="#views">Animating Views</a></li>
- <ol>
- <li><a href="#tween-animation">Tween animation</a></li>
-
- <li><a href="#frame-animation">Frame animation</a></li>
- </ol>
- </li>
- </ol>
+ <li><a href="#declaring-xml">Declaring Animations in XML</a></li>
+ </ol>
<h2>Key classes</h2>
@@ -52,201 +49,504 @@ page.title=Animation
<h2>Related samples</h2>
<ol>
- <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/index.html">API Demos</a></li>
+ <li><a href=
+ "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/index.html">API
+ Demos</a></li>
</ol>
-
</div>
</div>
- <p>The Android system provides a flexible animation system that allows you to animate
- almost anything, either programmatically or declaratively with XML. There are two
- animation systems that you can choose from: <a href="#property-animation">property
- animation</a> and <a href="#view-animation">view animation</a>. You can use whichever
- system that matches your needs, but use only one system for each object that you
- are animating.</p>
-
- <h2 id="property-animation">Property Animation</h2>
-
- <p>Introduced in Android 3.0, the property animation system allows you to animate
- object properties of any type. <code>int</code>, <code>float</code>,
- and hexadecimal color values are supported by default. You can animate any other type by telling the
- system how to calculate the values for that given type.</p>
+ <p>Introduced in Android 3.0, the property animation system is a robust framework that allows you
+ to animate almost anything. Property animation is not confined to objects drawn on the screen.
+ You can define an animation to change any object property over time, regardless of whether it
+ draws to the screen or not.The property animation system also has a few advantages over the view
+ animation system, which makes it more flexible to use.</p>
- <p>The property animation system allows you to define many aspects of an animation,
- such as:</p>
+ <p>The view animation system provides the capability to only animate View objects, so if
+ you wanted to animate non-View objects, you had to implement your own code to do so. The view
+ animation system also was constrained in the fact that it only exposed a few aspects of a View
+ object to animate, such as the scaling and rotation of a View but not the background color for
+ instance.</p>
+
+ <p>Another disadvantage of the view animation system is that it only modified where the
+ View was drawn, and not the actual View itself. For instance, if you animated a button to move
+ across the screen, the button draws correctly, but the actual location where you can click the
+ button does not change, so you have to implement your own logic to handle this. With the property
+ animation system, these constraints are completely removed, and you can animate any property of
+ any object, including View objects, and the object itself is actually modified.</p>
+
+ <p>The view animation system, however, takes less time to setup and requires less code to write.
+ If view animation accomplishes everything that you need to do, or if your existing code already
+ works the way you want, there is no need to use the property animation system.</p>
+
+ <h2 id="what">What is Property Animation?</h2>
+ A property animation changes a property's (a field in
+ an object) value over a specified length of time. To animate something, you specify the
+ object property that you want to animate, such as an object's position on the screen, how long
+ you want to animate it for, and what values you want to animate between. </p>
+
+ <p>The property animation system lets you define the following characteristics of an
+ animation:</p>
<ul>
- <li>Duration</li>
+ <li>Duration: You can specify the duration of an animation. The default length is 300 ms.</li>
- <li>Repeat amount and behavior</li>
+ <li>Time interpolation: You can specify how the values for the property are calculated as a
+ function of the animation's current elapsed time.</li>
- <li>Type of time interpolation</li>
+ <li>Repeat count and behavior: You can specify whether or not to have an animation repeat when
+ it reaches the end of a duration and how many times to repeat the animation. You can also
+ specify whether you want the animation to play back in reverse. Setting it to reverse plays
+ the animation forwards then backwards repeatedly, until the number of repeats is reached.</li>
- <li>Animator sets to play animations together, sequentially, or after specified
- delays</li>
+ <li>Animator sets: You can group animations into logical sets that play together or
+ sequentially or after specified delays.</li>
- <li>Frame refresh delay</li>
-
+ <li>Frame refresh delay: You can specify how often to refresh frames of your animation. The
+ default is set to refresh every 10 ms, but the speed in which your application can refresh frames is
+ ultimately dependent on how busy the system is overall and how fast the system can service the underlying timer.</li>
</ul>
- <p>Most of the property animation system's features can be found in
- {@link android.animation android.animation}. Because the
- <a href="#view-animation">view animation</a> system already
- defines many interpolators in {@link android.view.animation android.view.animation},
- you will use those to define your animation's interpolation in the property animation
- system as well.
+ <h3 id="how">How the property animation system works</h3>
+
+ <p>First, let's go over how an animation works with a simple example. Figure 1 depicts a
+ hypothetical object that is animated with its <code>x</code> property, which represents its
+ horizontal location on a screen. The duration of the animation is set to 40 ms and the distance
+ to travel is 40 pixels. Every 10 ms, which is the default frame refresh rate, the object moves
+ horizontally by 10 pixels. At the end of 40ms, the animation stops, and the object ends at
+ horizontal position 40. This is an example of an animation with linear interpolation, meaning the
+ object moves at a constant speed.</p><img src="{@docRoot}images/animation/animation-linear.png">
+
+ <p class="img-caption"><strong>Figure 1.</strong> Example of a linear animation</p>
+
+ <p>You can also specify animations to have a non-linear interpolation. Figure 2 illustrates a
+ hypothetical object that accelerates at the beginning of the animation, and decelerates at the
+ end of the animation. The object still moves 40 pixels in 40 ms, but non-linearly. In the
+ beginning, this animation accelerates up to the halfway point then decelerates from the
+ halfway point until the end of the animation. As Figure 2 shows, the distance traveled
+ at the beginning and end of the animation is less than in the middle.</p><img src=
+ "{@docRoot}images/animation/animation-nonlinear.png">
+
+ <p class="img-caption"><strong>Figure 2.</strong> Example of a non-linear animation</p>
+
+ <p>Let's take a detailed look at how the important components of the property animation system
+ would calculate animations like the ones illustrated above. Figure 3 depicts how the main classes
+ work with one another.</p><img src="{@docRoot}images/animation/valueanimator.png">
+
+ <p class="img-caption"><strong>Figure 3.</strong> How animations are calculated</p>
+
+ <p>The {@link android.animation.ValueAnimator} object keeps track of your animation's timing,
+ such as how long the animation has been running, and the current value of the property that it is
+ animating.</p>
+
+ <p>The {@link android.animation.ValueAnimator} encapsulates a {@link
+ android.animation.TimeInterpolator}, which defines animation interpolation, and a {@link
+ android.animation.TypeEvaluator}, which defines how to calculate values for the property being
+ animated. For example, in Figure 2, the {@link android.animation.TimeInterpolator} used would be
+ {@link android.view.animation.AccelerateDecelerateInterpolator} and the {@link
+ android.animation.TypeEvaluator} would be {@link android.animation.IntEvaluator}.</p>
+
+ <p>To start an animation, create a {@link android.animation.ValueAnimator} and give it the
+ starting and ending values for the property that you want to animate, along with the duration of
+ the animation. When you call {@link android.animation.ValueAnimator#start start()} the animation
+ begins. During the whole animation, the {@link android.animation.ValueAnimator} calculates an <em>elapsed fraction</em>
+ between 0 and 1, based on the duration of the animation and how much time has elapsed. The
+ elapsed fraction represents the percentage of time that the animation has completed, 0 meaning 0%
+ and 1 meaning 100%. For example, in Figure 1, the elapsed fraction at t = 10 ms would be .25
+ because the total duration is t = 40 ms.</p>
+
+ <p>When the {@link android.animation.ValueAnimator} is done calculating an elapsed fraction, it
+ calls the {@link android.animation.TimeInterpolator} that is currently set, to calculate an
+ <em>interpolated fraction</em>. An interpolated fraction maps the elapsed fraction to a new
+ fraction that takes into account the time interpolation that is set. For example, in Figure 2,
+ because the animation slowly accelerates, the interpolated fraction, about .15, is less than the
+ elapsed fraction, .25, at t = 10 ms. In Figure 1, the interpolated fraction is always the same as
+ the elapsed fraction.</p>
+
+ <p>When the interpolated fraction is calculated, {@link android.animation.ValueAnimator} calls
+ the appropriate {@link android.animation.TypeEvaluator}, to calculate the value of the
+ property that you are animating, based on the interpolated fraction, the starting value, and the
+ ending value of the animation. For example, in Figure 2, the interpolated fraction was .15 at t =
+ 10 ms, so the value for the property at that time would be .15 X (40 - 0), or 6.</p>
+
+ <!-- <p>When the final value is calculated, the {@link android.animation.ValueAnimator} calls the
+ {@link android.animation.ValueAnimator.AnimatorUpdateListener#onAnimationUpdate
+ onAnimationUpdate()} method. Implement this callback to obtain the property value by
+ calling {@link android.animation.ValueAnimator#getAnimatedValue getAnimatedValue()} and set the
+ value for the property in the object that you are animating. Setting the property doesn't redraw
+ the object on the screen, so you need to call {@link
+ android.view.View#invalidate invalidate()} to refresh the View that the object
+ resides in. If the object is actually a View object, then the system calls {@link
+ android.view.View#invalidate invalidate()} when the property is changed.
+ The system redraws the window and the {@link android.animation.ValueAnimator}
+ repeats the process.</p>-->
+
+ <p>The <code>com.example.android.apis.animation</code> package in the <a href=
+ "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/index.html">API
+ Demos</a> sample project provides many examples on how to use the property
+ animation system.</p>
+
+ <h2>API Overview</h2>
+
+ <p>You can find most of the property animation system's APIs in {@link android.animation
+ android.animation}. Because the view animation system already
+ defines many interpolators in {@link android.view.animation android.view.animation}, you can use
+ those interpolators in the property animation system as well. The following tables describe the main
+ components of the property animation system.</p>
+
+ <p>The {@link android.animation.Animator} class provides the basic structure for creating
+ animations. You normally do not use this class directly as it only provides minimal
+ functionality that must be extended to fully support animating values. The following
+ subclasses extend {@link android.animation.Animator}:
</p>
+ <p class="table-caption"><strong>Table 1.</strong> Animators</p>
+ <table>
+ <tr>
+ <th>Class</th>
+
+ <th>Description</th>
+ </tr>
+
+ <tr>
+ <td>{@link android.animation.ValueAnimator}</td>
+
+ <td>The main timing engine for property animation that also computes the values for the
+ property to be animated. It has all of the core functionality that calculates animation
+ values and contains the timing details of each animation, information about whether an
+ animation repeats, listeners that receive update events, and the ability to set custom
+ types to evaluate. There are two pieces to animating properties: calculating the animated
+ values and setting those values on the object and property that is being animated. {@link
+ android.animation.ValueAnimator} does not carry out the second piece, so you must listen
+ for updates to values calculated by the {@link android.animation.ValueAnimator} and
+ modify the objects that you want to animate with your own logic. See the section about
+ <a href="#value-animator">Animating with ValueAnimator</a> for more information.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.animation.ObjectAnimator}</td>
+
+ <td>A subclass of {@link android.animation.ValueAnimator} that allows you to set a target
+ object and object property to animate. This class updates the property accordingly when
+ it computes a new value for the animation. You want to use
+ {@link android.animation.ObjectAnimator} most of the time,
+ because it makes the process of animating values on target objects much easier. However,
+ you sometimes want to use {@link android.animation.ValueAnimator} directly because {@link
+ android.animation.ObjectAnimator} has a few more restrictions, such as requiring specific
+ acessor methods to be present on the target object.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.animation.AnimatorSet}</td>
+
+ <td>Provides a mechanism to group animations together so that they run in
+ relation to one another. You can set animations to play together, sequentially, or after
+ a specified delay. See the section about <a href="#choreography">Choreographing multiple
+ animations with Animator Sets</a> for more information.</td>
+ </tr>
+ </table>
- <p>The following items are the main components of the property animation system:</p>
+
+ <p>Evaluators tell the property animation system how to calculate values for a given
+ property. They take the timing data that is provided by an {@link android.animation.Animator}
+ class, the animation's start and end value, and calculate the animated values of the property
+ based on this data. The property animation system provides the following evaluators:</p>
+ <p class="table-caption"><strong>Table 2.</strong> Evaluators</p>
+ <table>
+ <tr>
+ <th>Class/Interface</th>
+
+ <th>Description</th>
+ </tr>
+
+ <tr>
+ <td>{@link android.animation.IntEvaluator}</td>
+
+ <td>The default evaluator to calculate values for <code>int</code> properties.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.animation.FloatEvaluator}</td>
+
+ <td>The default evaluator to calculate values for <code>float</code> properties.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.animation.ArgbEvaluator}</td>
- <dl>
- <dt><strong>Animators</strong></dt>
+ <td>The default evaluator to calculate values for color properties that are represented
+ as hexidecimal values.</td>
+ </tr>
- <dd>
- The {@link android.animation.Animator} class provides the basic structure for
- creating animations. You normally do not use this class directly as it only provides
- minimal functionality that must be extended to fully support animating values.
- The following subclasses extend {@link android.animation.Animator}, which you might find more useful:
+ <tr>
+ <td>{@link android.animation.TypeEvaluator}</td>
- <ul>
- <li>{@link android.animation.ValueAnimator} is the main timing engine for
- property animation and computes the values for the property to be animated.
- {@link android.animation.ValueAnimator} only computes the animation values and is
- not aware of the specific object and property that is being animated or what the
- values might be used for. You must listen for updates to values calculated by the
- {@link android.animation.ValueAnimator} and process the data with your own logic.
- See the section about <a href="#value-animator">Animating with ValueAnimator</a>
- for more information.</li>
-
- <li>{@link android.animation.ObjectAnimator} is a subclass of {@link
- android.animation.ValueAnimator} and allows you to set a target object and object
- property to animate. This class is aware of the object and property to be
- animated, and updates the property accordingly when it computes a new value for
- the animation. See the section about <a href="#object-animator">
- Animating with ObjectAnimator</a> for more information.</li>
-
- <li>{@link android.animation.AnimatorSet} provides a mechanism to group
- animations together so that they are rendered in relation to one another. You can
- set animations to play together, sequentially, or after a specified delay.
- See the section about <a href="#choreography">
- Choreographing multiple animations with Animator Sets</a> for more information.</li>
- </ul>
- </dd>
-
- <dt><strong>Evaluators</strong></dt>
-
- <dd>
- <p>If you are animating an object property that is <em>not</em> an <code>int</code>,
- <code>float</code>, or color, implement the {@link android.animation.TypeEvaluator}
- interface to specify how to compute the object property's animated values. You give
- a {@link android.animation.TypeEvaluator} the timing data that is provided by an
- {@link android.animation.Animator} class, the animation's start and end value, and
- provide logic that computes the animated values of the property based on this data.</p>
-
- <p>You can also specify a custom {@link android.animation.TypeEvaluator} for
- <code>int</code>, <code>float</code>, and color values as well, if you want to
- process those types differently than the default behavior.</p>
-
- <p>See <a href="#type-evaluator">Using a TypeEvaluator</a> for more information on
- how to write a custom evaluator.</p>
- </dd>
-
- <dt><strong>Interpolators</strong></dt>
-
- <dd>
- <p>A time interpolator defines how specific values in an animation are calculated
- as a function of time. For example, you can specify animations to happen linearly
- across the whole animation, meaning the animation moves evenly the entire time, or
- you can specify animations to use non-linear time, for example, using acceleration
- or deceleration at the beginning or end of the animation.</p>
-
- <p>The Android system provides a set of common interpolators in
- {@link android.view.animation android.view.animation}. If none of these suits your needs, you
- can implement the {@link android.animation.TimeInterpolator} interface and create
- your own. See <a href="#interpolators">Using interpolators</a> for more information on
- how to write a custom interpolator.</p>
- </dd>
- </dl>
-
-
- <p>The <code>com.example.android.apis.animation</code> package in the <a href=
- "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/index.html">
- API Demos</a> sample project also provides a good overview and many examples on how to
- use the property animation system.</p>
-
-
- <h3>How the property animation system calculates animated values</h3>
-
- <p>When you call {@link android.animation.ValueAnimator#start start()} to begin an animation,
- the {@link android.animation.ValueAnimator} calculates
- an <em>elapsed fraction</em> between 0 and 1, based on the duration of the animation
- and how much time has elapsed. The elapsed fraction represents the percentage of time
- that the animation has completed, 0 meaning 0% and 1 meaning 100%. The Animator then
- calls the {@link android.animation.TimeInterpolator} that is currently set,
- to calculate an <em>eased fraction</em>,
- which is a modified value of the elapsed fraction that takes into account the interpolator that
- is set (time interpolation is often referred to as <em>easing</em>). The eased fraction
- is the final value that is used to animate the property.</p>
-
- <p>Once the eased fraction is calculated, {@link android.animation.ValueAnimator} calls
- the appropriate {@link android.animation.TypeEvaluator} to calculate the final value of
- the property that you are animating, based on the eased fraction, the starting value,
- and ending value of the animation.</p>
-
- <h3 id="value-animator">Animating with ValueAnimator</h3>
-
- <p>The {@link android.animation.ValueAnimator} class lets you animate values of some
- type for the duration of an animation by specifying a set of <code>int</code>,
- <code>float</code>, or color values to animate over and the duration of the animation.
- You obtain a {@link android.animation.ValueAnimator} by calling one of its factory
- methods: {@link android.animation.ValueAnimator#ofInt ofInt()},
- {@link android.animation.ValueAnimator#ofFloat ofFloat()},
- or {@link android.animation.ValueAnimator#ofObject ofObject()}. For example:</p>
-
- <pre>ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
+ <td>An interface that allows you to create your own evaluator. If you are animating an
+ object property that is <em>not</em> an <code>int</code>, <code>float</code>, or color,
+ you must implement the {@link android.animation.TypeEvaluator} interface to specify how
+ to compute the object property's animated values. You can also specify a custom {@link
+ android.animation.TypeEvaluator} for <code>int</code>, <code>float</code>, and color
+ values as well, if you want to process those types differently than the default behavior.
+ See the section about <a href="#type-evaluator">Using a TypeEvaluator</a> for more
+ information on how to write a custom evaluator.</td>
+ </tr>
+ </table>
+
+
+
+
+ <p>A time interpolator defines how specific values in an animation are calculated as a
+ function of time. For example, you can specify animations to happen linearly across the whole
+ animation, meaning the animation moves evenly the entire time, or you can specify animations
+ to use non-linear time, for example, accelerating at the beginning and decelerating at the
+ end of the animation. Table 3 describes the interpolators that are contained in {@link
+ android.view.animation android.view.animation}. If none of the provided interpolators suits
+ your needs, implement the {@link android.animation.TimeInterpolator} interface and create your own. See <a href=
+ "#interpolators">Using interpolators</a> for more information on how to write a custom
+ interpolator.</p>
+ <p class="table-caption"><strong>Table 3.</strong> Interpolators</p>
+ <table>
+ <tr>
+ <th>Class/Interface</th>
+
+ <th>Description</th>
+ </tr>
+
+ <tr>
+ <td>{@link android.view.animation.AccelerateDecelerateInterpolator}</td>
+
+ <td>An interpolator whose rate of change starts and ends slowly but accelerates
+ through the middle.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.view.animation.AccelerateInterpolator}</td>
+
+ <td>An interpolator whose rate of change starts out slowly and then
+ accelerates.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.view.animation.AnticipateInterpolator}</td>
+
+ <td>An interpolator whose change starts backward then flings forward.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.view.animation.AnticipateOvershootInterpolator}</td>
+
+ <td>An interpolator whose change starts backward, flings forward and overshoots
+ the target value, then finally goes back to the final value.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.view.animation.BounceInterpolator}</td>
+
+ <td>An interpolator whose change bounces at the end.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.view.animation.CycleInterpolator}</td>
+
+ <td>An interpolator whose animation repeats for a specified number of cycles.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.view.animation.DecelerateInterpolator}</td>
+
+ <td>An interpolator whose rate of change starts out quickly and and then
+ decelerates.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.view.animation.LinearInterpolator}</td>
+
+ <td>An interpolator whose rate of change is constant.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.view.animation.OvershootInterpolator}</td>
+
+ <td>An interpolator whose change flings forward and overshoots the last value then
+ comes back.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.animation.TimeInterpolator}</td>
+
+ <td>An interface that allows you to implement your own interpolator.</td>
+ </tr>
+ </table>
+
+ <h2 id="value-animator">Animating with ValueAnimator</h2>
+
+ <p>The {@link android.animation.ValueAnimator} class lets you animate values of some type for the
+ duration of an animation by specifying a set of <code>int</code>, <code>float</code>, or color
+ values to animate through. You obtain a {@link android.animation.ValueAnimator} by calling one of
+ its factory methods: {@link android.animation.ValueAnimator#ofInt ofInt()}, {@link
+ android.animation.ValueAnimator#ofFloat ofFloat()}, or {@link
+ android.animation.ValueAnimator#ofObject ofObject()}. For example:</p>
+ <pre>
+ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.start();
</pre>
- <p>In this code, the {@link android.animation.ValueAnimator} starts
- calculating the values of the animation, between 0 and 1, for
- a duration of 1000 ms, when the <code>start()</code> method runs.</p>
+ <p>In this code, the {@link android.animation.ValueAnimator} starts calculating the values of the
+ animation, between 0 and 1, for a duration of 1000 ms, when the <code>start()</code> method
+ runs.</p>
<p>You can also specify a custom type to animate by doing the following:</p>
-
- <pre>ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
+ <pre>
+ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();
</pre>
- <p>In this code, the {@link android.animation.ValueAnimator} starts
- calculating the values of the animation, between <code>startPropertyValue</code> and
- <code>endPropertyValue</code> using the logic supplied by <code>MyTypeEvaluator</code>
- for a duration of 1000 ms, when the {@link android.animation.ValueAnimator#start start()}
- method runs.</p>
+ <p>In this code, the {@link android.animation.ValueAnimator} starts calculating the values of the
+ animation, between <code>startPropertyValue</code> and <code>endPropertyValue</code> using the
+ logic supplied by <code>MyTypeEvaluator</code> for a duration of 1000 ms, when the {@link
+ android.animation.ValueAnimator#start start()} method runs.</p>
+
+ <p>The previous code snippets, however, has no real effect on an object, because the {@link
+ android.animation.ValueAnimator} does not operate on objects or properties directly. The most likely thing
+ that you want to do is modify the objects that you want to animate with these calculated values. You do
+ this by defining listeners in the {@link android.animation.ValueAnimator} to appropriately handle important events
+ during the animation's lifespan, such as frame updates. When implementing the listeners, you can
+ obtain the calculated value for that specific frame refresh by calling {@link
+ android.animation.ValueAnimator#getAnimatedValue getAnimatedValue()}. For more information on listeners,
+ see the section about <a href="#listeners">Animation Listeners</a>.
+
+ <h2 id="object-animator">Animating with ObjectAnimator</h2>
+
+ <p>The {@link android.animation.ObjectAnimator} is a subclass of the {@link
+ android.animation.ValueAnimator} (discussed in the previous section) and combines the timing
+ engine and value computation of {@link android.animation.ValueAnimator} with the ability to
+ animate a named property of a target object. This makes animating any object much easier, as you
+ no longer need to implement the {@link android.animation.ValueAnimator.AnimatorUpdateListener},
+ because the animated property updates automatically.</p>
+
+ <p>Instantiating an {@link android.animation.ObjectAnimator} is similar to a {@link
+ android.animation.ValueAnimator}, but you also specify the object and the name of that object's property (as
+ a String) along with the values to animate between:</p>
+ <pre>
+ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
+anim.setDuration(1000);
+anim.start();
+</pre>
- <p>The previous code snippets, however, do not affect an object, because the {@link
- android.animation.ValueAnimator} does not operate on objects or properties directly. To
- use the results of a {@link android.animation.ValueAnimator}, you must define listeners
- in the {@link android.animation.ValueAnimator} to appropriately handle important events
- during the animation's lifespan, such as frame updates. You can implement the following
- interfaces to create listeners for {@link android.animation.ValueAnimator}:</p>
+ <p>To have the {@link android.animation.ObjectAnimator} update properties correctly, you must do
+ the following:</p>
+
+ <ul>
+ <li>The object property that you are animating must have a setter function (in camel case) in the form of
+ <code>set&lt;propertyName&gt;()</code>. Because the {@link android.animation.ObjectAnimator}
+ automatically updates the property during animation, it must be able to access the property
+ with this setter method. For example, if the property name is <code>foo</code>, you need to
+ have a <code>setFoo()</code> method. If this setter method does not exist, you have three
+ options:
+
+ <ul>
+ <li>Add the setter method to the class if you have the rights to do so.</li>
+
+ <li>Use a wrapper class that you have rights to change and have that wrapper receive the
+ value with a valid setter method and forward it to the original object.</li>
+
+ <li>Use {@link android.animation.ValueAnimator} instead.</li>
+ </ul>
+ </li>
+
+ <li>If you specify only one value for the <code>values...</code> parameter in one of the {@link
+ android.animation.ObjectAnimator} factory methods, it is assumed to be the ending value of the
+ animation. Therefore, the object property that you are animating must have a getter function
+ that is used to obtain the starting value of the animation. The getter function must be in the
+ form of <code>get&lt;propertyName&gt;()</code>. For example, if the property name is
+ <code>foo</code>, you need to have a <code>getFoo()</code> method.</li>
+
+ <li>The getter (if needed) and setter methods of the property that you are animating must
+ operate on the same type as the starting and ending values that you specify to {@link
+ android.animation.ObjectAnimator}. For example, you must have
+ <code>targetObject.setPropName(float)</code> and <code>targetObject.getPropName(float)</code>
+ if you construct the following {@link android.animation.ObjectAnimator}:
+ <pre>
+ObjectAnimator.ofFloat(targetObject, "propName", 1f)
+</pre>
+ </li>
+
+ <li>Depending on what property or object you are animating, you might need to call the {@link
+ android.view.View#invalidate invalidate()} method on a View force the screen to redraw itself with the
+ updated animated values. You do this in the
+ {@link android.animation.ValueAnimator.AnimatorUpdateListener#onAnimationUpdate onAnimationUpdate()}
+ callback. For example, animating the color property of a Drawable object only cause updates to the
+ screen when that object redraws itself. All of the property setters on View, such as
+ {@link android.view.View#setAlpha setAlpha()} and {@link android.view.View#setTranslationX setTranslationX()}
+ invalidate the View properly, so you do not need to invalidate the View when calling these
+ methods with new values. For more information on listeners, see the section about <a href="#listeners">Animation Listeners</a>.
+ </li>
+ </ul>
+
+ <h2 id="choreography">Choreographing Multiple Animations with AnimatorSet</h2>
+
+ <p>In many cases, you want to play an animation that depends on when another animation starts or
+ finishes. The Android system lets you bundle animations together into an {@link
+ android.animation.AnimatorSet}, so that you can specify whether to start animations
+ simultaneously, sequentially, or after a specified delay. You can also nest {@link
+ android.animation.AnimatorSet} objects within each other.</p>
+
+ <p>The following sample code taken from the <a href=
+ "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/BouncingBalls.html">Bouncing
+ Balls</a> sample (modified for simplicity) plays the following {@link android.animation.Animator}
+ objects in the following manner:</p>
+
+ <ol>
+ <li>Plays <code>bounceAnim</code>.</li>
+
+ <li>Plays <code>squashAnim1</code>, <code>squashAnim2</code>, <code>stretchAnim1</code>, and
+ <code>stretchAnim2</code> at the same time.</li>
+
+ <li>Plays <code>bounceBackAnim</code>.</li>
+
+ <li>Plays <code>fadeAnim</code>.</li>
+ </ol>
+ <pre>
+AnimatorSet bouncer = new AnimatorSet();
+bouncer.play(bounceAnim).before(squashAnim1);
+bouncer.play(squashAnim1).with(squashAnim2);
+bouncer.play(squashAnim1).with(stretchAnim1);
+bouncer.play(squashAnim1).with(stretchAnim2);
+bouncer.play(bounceBackAnim).after(stretchAnim2);
+ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
+fadeAnim.setDuration(250);
+AnimatorSet animatorSet = new AnimatorSet();
+animatorSet.play(bouncer).before(fadeAnim);
+animatorSet.start();
+</pre>
+
+ <p>For a more complete example on how to use animator sets, see the <a href=
+ "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/BouncingBalls.html">Bouncing
+ Balls</a> sample in APIDemos.</p>
+
+<h2 id="listeners">Animation Listeners</h2>
+<p>
+You can listen for important events during an animation's duration with the listeners described below.
+</p>
<ul>
<li>{@link android.animation.Animator.AnimatorListener}
<ul>
- <li>{@link android.animation.Animator.AnimatorListener#onAnimationStart
- onAnimationStart()} - Called when the animation starts</li>
+ <li>{@link android.animation.Animator.AnimatorListener#onAnimationStart onAnimationStart()}
+ - Called when the animation starts.</li>
- <li>{@link android.animation.Animator.AnimatorListener#onAnimationEnd
- onAnimationEnd()} - Called when the animation ends.</li>
+ <li>{@link android.animation.Animator.AnimatorListener#onAnimationEnd onAnimationEnd()} -
+ Called when the animation ends.</li>
<li>{@link android.animation.Animator.AnimatorListener#onAnimationRepeat
onAnimationRepeat()} - Called when the animation repeats itself.</li>
<li>{@link android.animation.Animator.AnimatorListener#onAnimationCancel
- onAnimationCancel()} - Called when the animation is canceled.</li>
+ onAnimationCancel()} - Called when the animation is canceled. A cancelled animation
+ also calls {@link android.animation.Animator.AnimatorListener#onAnimationEnd onAnimationEnd()},
+ regardless of how they were ended.</li>
</ul>
</li>
@@ -254,167 +554,173 @@ animation.start();
<ul>
<li>
- <p>{@link
- android.animation.ValueAnimator.AnimatorUpdateListener#onAnimationUpdate
- onAnimationUpdate()} - called on every frame of the animation.
- Listen to this event to use the calculated values generated by
- {@link android.animation.ValueAnimator} during an animation. To use the value,
- query the {@link android.animation.ValueAnimator} object passed into the event
- to get the current animated value with the
- {@link android.animation.ValueAnimator#getAnimatedValue getAnimatedValue()} method.</p>
-
- <p>If you are animating your own custom object (not View objects), this
- callback must also call the {@link android.view.View#invalidate invalidate()}
- method to force a redraw of the screen. If you are animating View objects,
- {@link android.view.View#invalidate invalidate()} is automatically called when
- a property of the View is changed.</p>
+ <p>{@link android.animation.ValueAnimator.AnimatorUpdateListener#onAnimationUpdate
+ onAnimationUpdate()} - called on every frame of the animation. Listen to this event to
+ use the calculated values generated by {@link android.animation.ValueAnimator} during an
+ animation. To use the value, query the {@link android.animation.ValueAnimator} object
+ passed into the event to get the current animated value with the {@link
+ android.animation.ValueAnimator#getAnimatedValue getAnimatedValue()} method. Implementing this
+ listener is required if you use {@link android.animation.ValueAnimator}. </p>
+
+ <p>
+ Depending on what property or object you are animating, you might need to call
+ {@link android.view.View#invalidate invalidate()} on a View to force that area of the
+ screen to redraw itself with the new animated values. For example, animating the
+ color property of a Drawable object only cause updates to the screen when that object
+ redraws itself. All of the property setters on View,
+ such as {@link android.view.View#setAlpha setAlpha()} and
+ {@link android.view.View#setTranslationX setTranslationX()} invalidate the View
+ properly, so you do not need to invalidate the View when calling these methods with new values.
+ </p>
+
</li>
</ul>
-
- <p>You can extend the {@link android.animation.AnimatorListenerAdapter} class
- instead of implementing the {@link android.animation.Animator.AnimatorListener}
- interface, if you do not want to implement all of the methods of the {@link
- android.animation.Animator.AnimatorListener} interface. The {@link
- android.animation.AnimatorListenerAdapter} class provides empty implementations of the
- methods that you can choose to override.</p>
</li>
</ul>
+<p>You can extend the {@link android.animation.AnimatorListenerAdapter} class instead of
+implementing the {@link android.animation.Animator.AnimatorListener} interface, if you do not
+want to implement all of the methods of the {@link android.animation.Animator.AnimatorListener}
+interface. The {@link android.animation.AnimatorListenerAdapter} class provides empty
+implementations of the methods that you can choose to override.</p>
<p>For example, the <a href=
- "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/BouncingBalls.html">
- Bouncing Balls</a> sample in the API demos creates an {@link
- android.animation.AnimatorListenerAdapter} for just the {@link
- android.animation.Animator.AnimatorListener#onAnimationEnd onAnimationEnd()}
+ "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/BouncingBalls.html">Bouncing
+ Balls</a> sample in the API demos creates an {@link android.animation.AnimatorListenerAdapter}
+ for just the {@link android.animation.Animator.AnimatorListener#onAnimationEnd onAnimationEnd()}
callback:</p>
-
- <pre>ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
+ <pre>
+ValueAnimatorAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
balls.remove(((ObjectAnimator)animation).getTarget());
-}</pre>
+}
+</pre>
- <h3 id="object-animator">Animating with ObjectAnimator</h3>
- <p>The {@link android.animation.ObjectAnimator} is a subclass of the {@link
- android.animation.ValueAnimator} (discussed in the previous section)
- and combines the timing engine and value computation
- of {@link android.animation.ValueAnimator} with the ability to animate a named property
- of a target object. This makes animating any object much easier, as you no longer need
- to implement the {@link android.animation.ValueAnimator.AnimatorUpdateListener}, because
- the animated property updates automatically.</p>
+ <h2 id="layout">Animating Layout Changes to ViewGroups</h2>
- <p>Instantiating an {@link android.animation.ObjectAnimator} is similar to a {@link
- android.animation.ValueAnimator}, but you also specify the object and that object's
- property (as a String) that you want to animate:</p>
- <pre>ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
-anim.setDuration(1000);
-anim.start();</pre>
+ <p>The property animation system provides the capability to animate changes to ViewGroup objects
+ as well as provide an easy way to animate View objects themselves.</p>
- <p>To have the {@link android.animation.ObjectAnimator} update properties correctly,
- you must do the following:</p>
+ <p>You can animate layout changes within a ViewGroup with the {@link
+ android.animation.LayoutTransition} class. Views inside a ViewGroup can go through an appearing
+ and disappearing animation when you add them to or remove them from a ViewGroup or when you call
+ a View's {@link android.view.View#setVisibility setVisibility()} method with {@link
+ android.view.View#VISIBLE}, android.view.View#INVISIBLE}, or {@link android.view.View#GONE}. The remaining Views in the
+ ViewGroup can also animate into their new positions when you add or remove Views. You can define
+ the following animations in a {@link android.animation.LayoutTransition} object by calling {@link
+ android.animation.LayoutTransition#setAnimator setAnimator()} and passing in an {@link
+ android.animation.Animator} object with one of the following {@link
+ android.animation.LayoutTransition} constants:</p>
<ul>
- <li>The object property that you are animating must have a setter function in the
- form of <code>set&lt;propertyName&gt;()</code>. Because the {@link
- android.animation.ObjectAnimator} automatically updates the property during
- animation, it must be able to access the property with this setter method. For
- example, if the property name is <code>foo</code>, you need to have a
- <code>setFoo()</code> method. If this setter method does not exist, you have three
- options:
+ <li><code>APPEARING</code> - A flag indicating the animation that runs on items that are
+ appearing in the container.</li>
- <ul>
- <li>Add the setter method to the class if you have the rights to do so.</li>
+ <li><code>CHANGE_APPEARING</code> - A flag indicating the animation that runs on items that are
+ changing due to a new item appearing in the container.</li>
- <li>Use a wrapper class that you have rights to change and have that wrapper
- receive the value with a valid setter method and forward it to the original
- object.</li>
+ <li><code>DISAPPEARING</code> - A flag indicating the animation that runs on items that are
+ disappearing from the container.</li>
- <li>Use {@link android.animation.ValueAnimator} instead.</li>
- </ul>
- </li>
+ <li><code>CHANGE_DISAPPEARING</code> - A flag indicating the animation that runs on items that
+ are changing due to an item disappearing from the container.</li>
+ </ul>
- <li>If you specify only one value for the <code>values...</code> parameter,
- in one of the {@link android.animation.ObjectAnimator} factory methods, it is assumed to be
- the ending value of the animation. Therefore, the object property that you are
- animating must have a getter function that is used to obtain the starting value of
- the animation. The getter function must be in the form of
- <code>get&lt;propertyName&gt;()</code>. For example, if the property name is
- <code>foo</code>, you need to have a <code>getFoo()</code> method.</li>
+ <p>You can define your own custom animations for these four types of events to customize the look
+ of your layout transitions or just tell the animation system to use the default animations.</p>
+
+ <p>The <a href=
+ "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/LayoutAnimations.html">
+ LayoutAnimations</a> sample in API Demos shows you how to define animations for layout
+ transitions and then set the animations on the View objects that you want to animate.</p>
+
+ <p>The <a href=
+ "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/LayoutAnimationsByDefault.html">
+ LayoutAnimationsByDefault</a> and its corresponding <a href=
+ "{@docRoot}resources/samples/ApiDemos/res/layout/layout_animations_by_default.html">layout_animations_by_default.xml</a>
+ layout resource file show you how to enable the default layout transitions for ViewGroups in XML.
+ The only thing that you need to do is to set the <code>android:animateLayoutchanges</code>
+ attribute to <code>true</code> for the ViewGroup. For example:</p>
+ <pre>
+&lt;LinearLayout
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:id="@+id/verticalContainer"
+ android:animateLayoutChanges="true" /&gt;
+</pre>
- <li>The getter (if needed) and setter methods of the property that you are animating must
- return the same type as the starting and ending values that you specify to {@link
- android.animation.ObjectAnimator}. For example, you must have
- <code>targetObject.setPropName(float)</code> and
- <code>targetObject.getPropName(float)</code> if you construct the following {@link
- android.animation.ObjectAnimator}:
- <pre>ObjectAnimator.ofFloat(targetObject, "propName", 1f)</pre>
- </li>
- </ul>
+ <p>Setting this attribute to true automatically animates Views that are added or removed from the
+ ViewGroup as well as the remaining Views in the ViewGroup.</p>
- <h3 id="type-evaluator">Using a TypeEvaluator</h3>
+ <h2 id="type-evaluator">Using a TypeEvaluator</h2>
- <p>If you want to animate a type that is unknown to the Android system,
- you can create your own evaluator by implementing the {@link
- android.animation.TypeEvaluator} interface. The types that are known by the Android
- system are <code>int</code>, <code>float</code>, or a color, which are supported by the
- {@link android.animation.IntEvaluator}, {@link android.animation.FloatEvaluator}, and
- {@link android.animation.ArgbEvaluator} type evaluators.</p>
+ <p>If you want to animate a type that is unknown to the Android system, you can create your own
+ evaluator by implementing the {@link android.animation.TypeEvaluator} interface. The types that
+ are known by the Android system are <code>int</code>, <code>float</code>, or a color, which are
+ supported by the {@link android.animation.IntEvaluator}, {@link
+ android.animation.FloatEvaluator}, and {@link android.animation.ArgbEvaluator} type
+ evaluators.</p>
<p>There is only one method to implement in the {@link android.animation.TypeEvaluator}
- interface, the {@link android.animation.TypeEvaluator#evaluate evaluate()} method.
- This allows the animator that you are using to return an
- appropriate value for your animated property at the current point of the animation. The
- {@link android.animation.FloatEvaluator} class demonstrates how to do this:</p>
- <pre>public class FloatEvaluator implements TypeEvaluator {
+ interface, the {@link android.animation.TypeEvaluator#evaluate evaluate()} method. This allows
+ the animator that you are using to return an appropriate value for your animated property at the
+ current point of the animation. The {@link android.animation.FloatEvaluator} class demonstrates
+ how to do this:</p>
+ <pre>
+public class FloatEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startFloat = ((Number) startValue).floatValue();
return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
}
-}</pre>
-
- <p class="note"><strong>Note:</strong> When {@link android.animation.ValueAnimator} (or
- {@link android.animation.ObjectAnimator}) runs, it calculates a current elapsed
- fraction of the animation (a value between 0 and 1) and then calculates an eased
- version of that depending on what interpolator that you are using. The eased fraction
- is what your {@link android.animation.TypeEvaluator} receives through the <code>fraction</code>
- parameter, so you do not have to take into account the interpolator
- when calculating animated values.</p>
-
- <h3 id="interpolators">Using interpolators</h3>
-
- <p>An interpolator define how specific values in an animation are
- calculated as a function of time. For example, you can specify animations to happen
- linearly across the whole animation, meaning the animation moves evenly the entire
- time, or you can specify animations to use non-linear time, for example, using
- acceleration or deceleration at the beginning or end of the animation.</p>
-
- <p>Interpolators in the animation system receive a fraction from Animators that represent the elapsed time
- of the animation. Interpolators modify this fraction to coincide with the type of
- animation that it aims to provide. The Android system provides a set of common
- interpolators in the {@link android.view.animation android.view.animation package}. If
- none of these suit your needs, you can implement the {@link
- android.animation.TimeInterpolator} interface and create your own.</p>
+}
+</pre>
+
+ <p class="note"><strong>Note:</strong> When {@link android.animation.ValueAnimator} (or {@link
+ android.animation.ObjectAnimator}) runs, it calculates a current elapsed fraction of the
+ animation (a value between 0 and 1) and then calculates an interpolated version of that depending
+ on what interpolator that you are using. The interpolated fraction is what your {@link
+ android.animation.TypeEvaluator} receives through the <code>fraction</code> parameter, so you do
+ not have to take into account the interpolator when calculating animated values.</p>
+
+ <h2 id="interpolators">Using Interpolators</h2>
+
+ <p>An interpolator define how specific values in an animation are calculated as a function of
+ time. For example, you can specify animations to happen linearly across the whole animation,
+ meaning the animation moves evenly the entire time, or you can specify animations to use
+ non-linear time, for example, using acceleration or deceleration at the beginning or end of the
+ animation.</p>
+
+ <p>Interpolators in the animation system receive a fraction from Animators that represent the
+ elapsed time of the animation. Interpolators modify this fraction to coincide with the type of
+ animation that it aims to provide. The Android system provides a set of common interpolators in
+ the {@link android.view.animation android.view.animation package}. If none of these suit your
+ needs, you can implement the {@link android.animation.TimeInterpolator} interface and create your
+ own.</p>
<p>As an example, how the default interpolator {@link
android.view.animation.AccelerateDecelerateInterpolator} and the {@link
- android.view.animation.LinearInterpolator} calculate eased fractions are compared below. The {@link
- android.view.animation.LinearInterpolator} has no effect on the elapsed fraction,
- because a linear interpolation is calculated the same way as the elapsed fraction. The
- {@link android.view.animation.AccelerateDecelerateInterpolator} accelerates into the
- animation and decelerates out of it. The following methods define the logic for these
- interpolators:</p>
+ android.view.animation.LinearInterpolator} calculate interpolated fractions are compared below.
+ The {@link android.view.animation.LinearInterpolator} has no effect on the elapsed fraction. The {@link
+ android.view.animation.AccelerateDecelerateInterpolator} accelerates into the animation and
+ decelerates out of it. The following methods define the logic for these interpolators:</p>
<p><strong>AccelerateDecelerateInterpolator</strong></p>
- <pre>public float getInterpolation(float input) {
+ <pre>
+public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
-}</pre>
+}
+</pre>
<p><strong>LinearInterpolator</strong></p>
- <pre>public float getInterpolation(float input) {
+ <pre>
+public float getInterpolation(float input) {
return input;
-}</pre>
+}
+</pre>
<p>The following table represents the approximate values that are calculated by these
interpolators for an animation that lasts 1000ms:</p>
@@ -423,9 +729,9 @@ anim.start();</pre>
<tr>
<th>ms elapsed</th>
- <th>Elapsed fraction/Eased fraction (Linear)</th>
+ <th>Elapsed fraction/Interpolated fraction (Linear)</th>
- <th>Eased fraction (Accelerate/Decelerate)</th>
+ <th>Interpolated fraction (Accelerate/Decelerate)</th>
</tr>
<tr>
@@ -477,152 +783,167 @@ anim.start();</pre>
</tr>
</table>
- <p>As the table shows, the {@link android.view.animation.LinearInterpolator} changes
- the values at the same speed, .2 for every 200ms that passes. The {@link
- android.view.animation.AccelerateDecelerateInterpolator} changes the values faster than
- {@link android.view.animation.LinearInterpolator} between 200ms and 600ms and slower
- between 600ms and 1000ms.</p>
-
- <h3 id="keyframes">Specifying keyframes</h3>
-
- <p>A {@link android.animation.Keyframe} object consists of a time/value pair that lets
- you define a specific state at a specific time of an animation. Each keyframe can also
- have its own interpolator to control the behavior of the animation in the interval
- between the previous keyframe's time and the time of this keyframe.</p>
-
- <p>To instantiate a {@link android.animation.Keyframe} object, you must use one of the
- factory methods, {@link android.animation.Keyframe#ofInt ofInt()}, {@link
- android.animation.Keyframe#ofFloat ofFloat()}, or {@link
- android.animation.Keyframe#ofObject ofObject()} to obtain the appropriate type of
- {@link android.animation.Keyframe}. You then call the {@link
- android.animation.PropertyValuesHolder#ofKeyframe ofKeyframe()} factory method to
- obtain a {@link android.animation.PropertyValuesHolder} object. Once you have the
- object, you can obtain an animator by passing in the {@link
- android.animation.PropertyValuesHolder} object and the object to animate. The following
- code snippet demonstrates how to do this:</p>
- <pre>Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
-Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);
+ <p>As the table shows, the {@link android.view.animation.LinearInterpolator} changes the values
+ at the same speed, .2 for every 200ms that passes. The {@link
+ android.view.animation.AccelerateDecelerateInterpolator} changes the values faster than {@link
+ android.view.animation.LinearInterpolator} between 200ms and 600ms and slower between 600ms and
+ 1000ms.</p>
+
+ <h2 id="keyframes">Specifying Keyframes</h2>
+
+ <p>A {@link android.animation.Keyframe} object consists of a time/value pair that lets you define
+ a specific state at a specific time of an animation. Each keyframe can also have its own
+ interpolator to control the behavior of the animation in the interval between the previous
+ keyframe's time and the time of this keyframe.</p>
+
+ <p>To instantiate a {@link android.animation.Keyframe} object, you must use one of the factory
+ methods, {@link android.animation.Keyframe#ofInt ofInt()}, {@link
+ android.animation.Keyframe#ofFloat ofFloat()}, or {@link android.animation.Keyframe#ofObject
+ ofObject()} to obtain the appropriate type of {@link android.animation.Keyframe}. You then call
+ the {@link android.animation.PropertyValuesHolder#ofKeyframe ofKeyframe()} factory method to
+ obtain a {@link android.animation.PropertyValuesHolder} object. Once you have the object, you can
+ obtain an animator by passing in the {@link android.animation.PropertyValuesHolder} object and
+ the object to animate. The following code snippet demonstrates how to do this:</p>
+ <pre>
+Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
+Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
rotationAnim.setDuration(5000ms);
</pre>
-<p>For a more complete example on how to use keyframes, see the <a href=
-"{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/MultiPropertyAnimation.html">
+
+ <p>For a more complete example on how to use keyframes, see the <a href=
+ "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/MultiPropertyAnimation.html">
MultiPropertyAnimation</a> sample in APIDemos.</p>
- <h3 id="choreography">Choreographing multiple animations with AnimatorSet</h3>
+ <h2 id="views">Animating Views</h2>
+
+ <p>The property animation system allow streamlined animation of View objects and offerse
+ a few advantages over the view animation system. The view
+ animation system transformed View objects by changing the way that they were drawn. This was
+ handled in the container of each View, because the View itself had no properties to manipulate.
+ This resulted in the View being animated, but caused no change in the View object itself. This
+ led to behavior such as an object still existing in its original location, even though it was
+ drawn on a different location on the screen. In Android 3.0, new properties and the corresponding
+ getter and setter methods were added to eliminate this drawback.</p>
+ <p>The property animation system
+ can animate Views on the screen by changing the actual properties in the View objects. In
+ addition, Views also automatically call the {@link android.view.View#invalidate invalidate()}
+ method to refresh the screen whenever its properties are changed. The new properties in the {@link
+ android.view.View} class that facilitate property animations are:</p>
- <p>In many cases, you want to play an animation that depends on when another animation
- starts or finishes. The Android system lets you bundle animations together into an
- {@link android.animation.AnimatorSet}, so that you can specify whether to start animations
- simultaneously, sequentially, or after a specified delay. You can also nest {@link
- android.animation.AnimatorSet} objects within each other.</p>
+ <ul>
+ <li><code>translationX</code> and <code>translationY</code>: These properties control where the
+ View is located as a delta from its left and top coordinates which are set by its layout
+ container.</li>
- <p>The following sample code taken from the <a href=
- "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/BouncingBalls.html">
- Bouncing Balls</a> sample (modified for simplicity) plays the following
- {@link android.animation.Animator} objects in the following manner:</p>
+ <li><code>rotation</code>, <code>rotationX</code>, and <code>rotationY</code>: These properties
+ control the rotation in 2D (<code>rotation</code> property) and 3D around the pivot point.</li>
- <ol>
- <li>Plays <code>bounceAnim</code>.</li>
+ <li><code>scaleX</code> and <code>scaleY</code>: These properties control the 2D scaling of a
+ View around its pivot point.</li>
- <li>Plays <code>squashAnim1</code>, <code>squashAnim2</code>,
- <code>stretchAnim1</code>, and <code>stretchAnim2</code> at the same time.</li>
+ <li><code>pivotX</code> and <code>pivotY</code>: These properties control the location of the
+ pivot point, around which the rotation and scaling transforms occur. By default, the pivot
+ point is located at the center of the object.</li>
- <li>Plays <code>bounceBackAnim</code>.</li>
+ <li><code>x</code> and <code>y</code>: These are simple utility properties to describe the
+ final location of the View in its container, as a sum of the left and top values and
+ translationX and translationY values.</li>
- <li>Plays <code>fadeAnim</code>.</li>
- </ol>
- <pre>AnimatorSet bouncer = new AnimatorSet();
-bouncer.play(bounceAnim).before(squashAnim1);
-bouncer.play(squashAnim1).with(squashAnim2);
-bouncer.play(squashAnim1).with(stretchAnim1);
-bouncer.play(squashAnim1).with(stretchAnim2);
-bouncer.play(bounceBackAnim).after(stretchAnim2);
-ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
-fadeAnim.setDuration(250);
-AnimatorSet animatorSet = new AnimatorSet();
-animatorSet.play(bouncer).before(fadeAnim);
-animatorSet.start();
+ <li><code>alpha</code>: Represents the alpha transparency on the View. This value is 1 (opaque)
+ by default, with a value of 0 representing full transparency (not visible).</li>
+ </ul>
+
+ <p>To animate a property of a View object, such as its color or rotation value, all you need to
+ do is create a property animator and specify the View property that you want to
+ animate. For example:</p>
+ <pre>
+ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
</pre>
- <p>For a more complete example on how to use animator sets, see the <a href=
- "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/BouncingBalls.html">
- Bouncing Balls</a> sample in APIDemos.</p>
+For more information on creating animators, see the sections on animating with
+<a href="#value-animator">ValueAnimator</a> and <a href="#object-animator">ObjectAnimator</a>
- <h3 id="declaring-xml">Declaring animations in XML</h3>
+ <h2 id="declaring-xml">Declaring Animations in XML</h2>
- <p>As with <a href="#view-animation">view animation</a>, you can declare property animations with
- XML instead of doing it programmatically. The following Android classes also have XML
- declaration support with the following XML tags:</p>
+ <p>The property animation system lets you declare property animations with XML instead of doing
+ it programmatically. The following Android classes have XML declaration support with the
+ following XML tags:</p>
<ul>
<li>{@link android.animation.ValueAnimator} - <code>&lt;animator&gt;</code></li>
<li>{@link android.animation.ObjectAnimator} - <code>&lt;objectAnimator&gt;</code></li>
- <li>{@link android.animation.AnimatorSet} - <code>&lt;AnimatorSet&gt;</code></li>
+ <li>{@link android.animation.AnimatorSet} - <code>&lt;set&gt;</code></li>
</ul>
<p>Both <code>&lt;animator&gt;</code> ({@link android.animation.ValueAnimator}) and
- <code>&lt;objectAnimator&gt;</code> ({@link android.animation.ObjectAnimator}) have the
- following attributes:</p>
+ <code>&lt;objectAnimator&gt;</code> ({@link android.animation.ObjectAnimator}) have the following
+ attributes:</p>
- <dl>
- <dt><code>android:duration</code></dt>
- <dd>The number of milliseconds that the animation runs.</dd>
-
- <dt><code>android:valueFrom</code> and <code>android:valueTo</code></dt>
- <dd>The values being animated
- between. These are restricted to numbers (<code>float</code> or <code>int</code>) in
- XML. They can be <code>float</code>, <code>int</code>, or any kind of
- <code>Object</code> when creating animations programmatically.</dd>
-
- <dt><code>android:valueType</code></dt>
- <dd>Set to either <code>"floatType"</code> or <code>"intType"</code>.</dd>
-
- <dt><code>android:startDelay</code></dt>
- <dd>The delay, in milliseconds, before the animation begins
- playing (after calling {@link android.animation.ValueAnimator#start start()}).</dd>
-
- <dt><code>android:repeatCount</code></dt>
- <dd>How many times to repeat an animation. Set to
- <code>"-1"</code> for infinite repeating or to a positive integer. For example, a value of
- <code>"1"</code> means that the animation is repeated once after the initial run of the
- animation, so the animation plays a total of two times. The default value is
- <code>"0"</code>.</dd>
-
- <dt><code>android:repeatMode</code></dt>
- <dd>How an animation behaves when it reaches the end of the
- animation. <code>android:repeatCount</code> must be set to a positive integer or
- <code>"-1"</code> for this attribute to have an effect. Set to <code>"reverse"</code> to
- have the animation reverse direction with each iteration or <code>"repeat"</code> to
- have the animation loop from the beginning each time.</dd>
+ <dl>
+ <dt><code>android:duration</code></dt>
+
+ <dd>The number of milliseconds that the animation runs. The default is 300 ms.</dd>
+
+ <dt><code>android:valueFrom</code> and <code>android:valueTo</code></dt>
+
+ <dd>The values being animated between. These are restricted to numbers (<code>float</code> or
+ <code>int</code>) and color values (such as #00ff00). They can be <code>float</code>, <code>int</code>, colors,
+ or any kind of <code>Object</code> when creating animations programmatically.</dd>
+
+ <dt><code>android:valueType</code></dt>
+
+ <dd>Set to either <code>"floatType"</code> or <code>"intType"</code>. The default is
+ <code>"floatType"</code> unless you specify something else or if the <code>valuesFrom</code>
+ and <code>valuesTo</code> values are colors.</dd>
+
+ <dt><code>android:startDelay</code></dt>
+
+ <dd>The delay, in milliseconds, before the animation begins playing (after calling {@link
+ android.animation.ValueAnimator#start start()}).</dd>
+
+ <dt><code>android:repeatCount</code></dt>
+
+ <dd>How many times to repeat an animation. Set to <code>"-1"</code> to infinitely repeat or
+ to a positive integer. For example, a value of <code>"1"</code> means that the animation is
+ repeated once after the initial run of the animation, so the animation plays a total of two
+ times. The default value is <code>"0"</code>, which means no repetition.</dd>
+
+ <dt><code>android:repeatMode</code></dt>
+
+ <dd>How an animation behaves when it reaches the end of the animation.
+ <code>android:repeatCount</code> must be set to a positive integer or <code>"-1"</code> for
+ this attribute to have an effect. Set to <code>"reverse"</code> to have the animation reverse
+ direction with each iteration or <code>"repeat"</code> to have the animation loop from the
+ beginning each time.</dd>
</dl>
-
+
<p>The <code>objectAnimator</code> ({@link android.animation.ObjectAnimator}) element has the
- additional attribute <code>propertyName</code>, that lets you specify the name of the
- property being animated. The <code>objectAnimator</code> element does not expose a
- <code>target</code> attribute, however, so you cannot set the object to animate in the
- XML declaration. You have to inflate the XML resource by calling
- {@link android.animation.AnimatorInflater#loadAnimator loadAnimator()} and call
- {@link android.animation.ObjectAnimator#setTarget setTarget()} to set the target object, before calling
- {@link android.animation.ObjectAnimator#start start()}.</p>
+ additional attribute <code>propertyName</code>, that lets you specify the name of the property
+ being animated. The <code>objectAnimator</code> element does not expose a <code>target</code>
+ attribute, however, so you cannot set the object to animate in the XML declaration. You have to
+ inflate the XML resource by calling {@link android.animation.AnimatorInflater#loadAnimator
+ loadAnimator()} and call {@link android.animation.ObjectAnimator#setTarget setTarget()} to set
+ the target object unlike the underlying {@link android.animation.ObjectAnimator},
+ before calling {@link android.animation.ObjectAnimator#start start()}.</p>
<p>The <code>set</code> element ({@link android.animation.AnimatorSet}) exposes a single
- attribute, <code>ordering</code>. Set this attribute to <code>together</code> (default)
- to play all the animations in this set at once. Set this attribute to
- <code>sequentially</code> to play the animations in the order they are declared.</p>
-
- <p>You can specify nested <code>set</code> tags to further group animations together.
- The animations that you want to group together should be children of the
- <code>set</code> tag and can define their own <code>ordering</code> attribute.</p>
-
- <p>As an example, this XML code creates an {@link android.animation.AnimatorSet} object
- that animates x and y at the same time (<code>together</code> is the default ordering
- when nothing is specified), then runs an animation that fades an object out:</p>
- <pre>&lt;set android:ordering="sequentially"&gt;
+ attribute, <code>ordering</code>. Set this attribute to <code>together</code> (default) to play
+ all the animations in this set at once. Set this attribute to <code>sequentially</code> to play
+ the animations in the order they are declared.</p>
+
+ <p>You can specify nested <code>set</code> tags to further group animations together. The
+ animations that you want to group together should be children of the <code>set</code> tag and can
+ define their own <code>ordering</code> attribute.</p>
+
+ <p>As an example, this XML code creates an {@link android.animation.AnimatorSet} object that
+ animates x and y at the same time, then runs an animation that fades an object out:</p>
+ <pre>
+&lt;set android:ordering="sequentially"&gt;
&lt;set&gt;
&lt;objectAnimator
android:propertyName="x"
@@ -639,190 +960,11 @@ animatorSet.start();
android:propertyName="alpha"
android:duration="500"
android:valueTo="0f"/&gt;
-&lt;/set&gt;</pre>
-
- <p>In order to run this animation, you must inflate the XML resources in your code to
- an {@link android.animation.AnimatorSet} object, and then set the target objects for all of
- the animations before starting the animation set. Calling {@link
- android.animation.AnimatorSet#setTarget setTarget()} sets a single target object for
- all children of the {@link android.animation.AnimatorSet}.</p>
-
- <h2 id="view-animation">View Animation</h2>You can use View Animation in any View
- object to perform tweened animation and frame by frame animation. Tween animation
- calculates the animation given information such as the start point, end point, size,
- rotation, and other common aspects of an animation. Frame by frame animation lets you
- load a series of Drawable resources one after another to create an animation.
-
- <h3 id="tween-animation">Tween Animation</h3>
-
- <p>A tween animation can perform a series of simple transformations (position, size,
- rotation, and transparency) on the contents of a View object. So, if you have a
- {@link android.widget.TextView} object, you can move, rotate, grow, or shrink the text. If it has a background
- image, the background image will be transformed along with the text. The {@link
- android.view.animation animation package} provides all the classes used in a tween
- animation.</p>
-
- <p>A sequence of animation instructions defines the tween animation, defined by either
- XML or Android code. As with defining a layout, an XML file is recommended because it's
- more readable, reusable, and swappable than hard-coding the animation. In the example
- below, we use XML. (To learn more about defining an animation in your application code,
- instead of XML, refer to the {@link android.view.animation.AnimationSet} class and
- other {@link android.view.animation.Animation} subclasses.)</p>
-
- <p>The animation instructions define the transformations that you want to occur, when
- they will occur, and how long they should take to apply. Transformations can be
- sequential or simultaneous &mdash; for example, you can have the contents of a TextView
- move from left to right, and then rotate 180 degrees, or you can have the text move and
- rotate simultaneously. Each transformation takes a set of parameters specific for that
- transformation (starting size and ending size for size change, starting angle and
- ending angle for rotation, and so on), and also a set of common parameters (for
- instance, start time and duration). To make several transformations happen
- simultaneously, give them the same start time; to make them sequential, calculate the
- start time plus the duration of the preceding transformation.</p>
-
- <p>The animation XML file belongs in the <code>res/anim/</code> directory of your
- Android project. The file must have a single root element: this will be either a single
- <code>&lt;alpha&gt;</code>, <code>&lt;scale&gt;</code>, <code>&lt;translate&gt;</code>,
- <code>&lt;rotate&gt;</code>, interpolator element, or <code>&lt;set&gt;</code> element
- that holds groups of these elements (which may include another
- <code>&lt;set&gt;</code>). By default, all animation instructions are applied
- simultaneously. To make them occur sequentially, you must specify the
- <code>startOffset</code> attribute, as shown in the example below.</p>
-
- <p>The following XML from one of the ApiDemos is used to stretch, then simultaneously
- spin and rotate a View object.</p>
- <pre>&lt;set android:shareInterpolator="false"&gt;
- &lt;scale
- android:interpolator="@android:anim/accelerate_decelerate_interpolator"
- android:fromXScale="1.0"
- android:toXScale="1.4"
- android:fromYScale="1.0"
- android:toYScale="0.6"
- android:pivotX="50%"
- android:pivotY="50%"
- android:fillAfter="false"
- android:duration="700" /&gt;
- &lt;set android:interpolator="@android:anim/decelerate_interpolator"&gt;
- &lt;scale
- android:fromXScale="1.4"
- android:toXScale="0.0"
- android:fromYScale="0.6"
- android:toYScale="0.0"
- android:pivotX="50%"
- android:pivotY="50%"
- android:startOffset="700"
- android:duration="400"
- android:fillBefore="false" /&gt;
- &lt;rotate
- android:fromDegrees="0"
- android:toDegrees="-45"
- android:toYScale="0.0"
- android:pivotX="50%"
- android:pivotY="50%"
- android:startOffset="700"
- android:duration="400" /&gt;
- &lt;/set&gt;
-&lt;/set&gt;</pre>
-
- <p>Screen coordinates (not used in this example) are (0,0) at the upper left hand
- corner, and increase as you go down and to the right.</p>
-
- <p>Some values, such as pivotX, can be specified relative to the object itself or
- relative to the parent. Be sure to use the proper format for what you want ("50" for
- 50% relative to the parent, or "50%" for 50% relative to itself).</p>
-
- <p>You can determine how a transformation is applied over time by assigning an {@link
- android.view.animation.Interpolator}. Android includes several Interpolator subclasses
- that specify various speed curves: for instance, {@link
- android.view.animation.AccelerateInterpolator} tells a transformation to start slow and
- speed up. Each one has an attribute value that can be applied in the XML.</p>
-
- <p>With this XML saved as <code>hyperspace_jump.xml</code> in the
- <code>res/anim/</code> directory of the project, the following code will reference
- it and apply it to an {@link android.widget.ImageView} object from the layout.</p>
- <pre>
-ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
-Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
-spaceshipImage.startAnimation(hyperspaceJumpAnimation);
-</pre>
-
- <p>As an alternative to <code>startAnimation()</code>, you can define a starting time
- for the animation with <code>{@link android.view.animation.Animation#setStartTime(long)
- Animation.setStartTime()}</code>, then assign the animation to the View with
- <code>{@link android.view.View#setAnimation(android.view.animation.Animation)
- View.setAnimation()}</code>.</p>
-
- <p>For more information on the XML syntax, available tags and attributes, see <a href=
- "{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
-
- <p class="note"><strong>Note:</strong> Regardless of how your animation may move or
- resize, the bounds of the View that holds your animation will not automatically adjust
- to accommodate it. Even so, the animation will still be drawn beyond the bounds of its
- View and will not be clipped. However, clipping <em>will occur</em> if the animation
- exceeds the bounds of the parent View.</p>
-
- <h3 id="frame-animation">Frame Animation</h3>
-
- <p>This is a traditional animation in the sense that it is created with a sequence of
- different images, played in order, like a roll of film. The {@link
- android.graphics.drawable.AnimationDrawable} class is the basis for frame
- animations.</p>
-
- <p>While you can define the frames of an animation in your code, using the {@link
- android.graphics.drawable.AnimationDrawable} class API, it's more simply accomplished
- with a single XML file that lists the frames that compose the animation. Like the tween
- animation above, the XML file for this kind of animation belongs in the
- <code>res/drawable/</code> directory of your Android project. In this case, the
- instructions are the order and duration for each frame of the animation.</p>
-
- <p>The XML file consists of an <code>&lt;animation-list&gt;</code> element as the root
- node and a series of child <code>&lt;item&gt;</code> nodes that each define a frame: a
- drawable resource for the frame and the frame duration. Here's an example XML file for
- a frame-by-frame animation:</p>
- <pre>
-&lt;animation-list xmlns:android="http://schemas.android.com/apk/res/android"
- android:oneshot="true"&gt;
- &lt;item android:drawable="@drawable/rocket_thrust1" android:duration="200" /&gt;
- &lt;item android:drawable="@drawable/rocket_thrust2" android:duration="200" /&gt;
- &lt;item android:drawable="@drawable/rocket_thrust3" android:duration="200" /&gt;
-&lt;/animation-list&gt;
+&lt;/set&gt;
</pre>
- <p>This animation runs for just three frames. By setting the
- <code>android:oneshot</code> attribute of the list to <var>true</var>, it will cycle
- just once then stop and hold on the last frame. If it is set <var>false</var> then the
- animation will loop. With this XML saved as <code>rocket_thrust.xml</code> in the
- <code>res/drawable/</code> directory of the project, it can be added as the background
- image to a View and then called to play. Here's an example Activity, in which the
- animation is added to an {@link android.widget.ImageView} and then animated when the
- screen is touched:</p>
- <pre>AnimationDrawable rocketAnimation;
-
-public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
- rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
- rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
-}
-
-public boolean onTouchEvent(MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- rocketAnimation.start();
- return true;
- }
- return super.onTouchEvent(event);
-}</pre>
-
- <p>It's important to note that the <code>start()</code> method called on the
- AnimationDrawable cannot be called during the <code>onCreate()</code> method of your
- Activity, because the AnimationDrawable is not yet fully attached to the window. If you
- want to play the animation immediately, without requiring interaction, then you might
- want to call it from the <code>{@link
- android.app.Activity#onWindowFocusChanged(boolean) onWindowFocusChanged()}</code>
- method in your Activity, which will get called when Android brings your window into
- focus.</p>
-
- <p>For more information on the XML syntax, available tags and attributes, see <a href=
- "{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p> \ No newline at end of file
+ <p>In order to run this animation, you must inflate the XML resources in your code to an {@link
+ android.animation.AnimatorSet} object, and then set the target objects for all of the animations
+ before starting the animation set. Calling {@link android.animation.AnimatorSet#setTarget
+ setTarget()} sets a single target object for all children of the {@link
+ android.animation.AnimatorSet}.</p> \ No newline at end of file
diff --git a/docs/html/guide/topics/graphics/renderscript.jd b/docs/html/guide/topics/graphics/renderscript.jd
new file mode 100644
index 000000000000..0ef8a22d9bbc
--- /dev/null
+++ b/docs/html/guide/topics/graphics/renderscript.jd
@@ -0,0 +1,710 @@
+page.title=3D Rendering and Computation with Renderscript
+@jd:body
+
+ <div id="qv-wrapper">
+ <div id="qv">
+ <h2>In this document</h2>
+
+ <ol>
+ <li><a href="#overview">Renderscript System Overview</a></li>
+
+ <li>
+ <a href="#api">API Overview</a>
+
+ <ol>
+ <li><a href="#native-api">Native Renderscript APIs</a></li>
+
+ <li><a href="#reflective-api">Reflective layer APIs</a></li>
+
+ <li><a href="#graphics-api">Graphics APIs</a></li>
+ </ol>
+ </li>
+
+ <li>
+ <a href="#developing">Developing a Renderscript application</a>
+
+ <ol>
+ <li><a href="#hello-graphics">The Hello Graphics application</a></li>
+ </ol>
+ </li>
+ </ol>
+ </div>
+ </div>
+
+ <p>The Renderscript system offers high performance 3D rendering and mathematical computations at
+ the native level. The Renderscript APIs are intended for developers who are comfortable with
+ developing in C (C99 standard) and want to maximize performance in their applications. The
+ Renderscript system improves performance by running as native code on the device, but it also
+ features cross-platform functionality. To achieve this, the Android build tools compile your
+ Renderscript <code>.rs</code> file to intermediate bytecode and package it inside your
+ application's <code>.apk</code> file. On the device, the bytecode is compiled (just-in-time) to
+ machine code that is further optimized for the device that it is running on. This eliminates the
+ need to target a specific architecture during the development process. The compiled code on the
+ device is cached, so subsequent uses of the Renderscript enabled application do not recompile the
+ intermediate code.</p>
+
+ <p>The disadvantage of the Renderscript system is that it adds complexity to the development and
+ debugging processes and is not a substitute for the Android system APIs. It is a portable native
+ language with pointers and explicit resource management. The target use is for performance
+ critical code where the existing Android APIs are not sufficient. If what you are rendering or
+ computing is very simple and does not require much processing power, you should still use the
+ Android APIs for ease of development. Debugging visibility can be limited, because the
+ Renderscript system can execute on processors other than the main CPU (such as the GPU), so if
+ this occurs, debugging becomes more difficult. Remember the tradeoffs between development and
+ debugging complexity versus performance when deciding to use Renderscript.</p>
+
+ <p>For an example of Renderscript in action, see the 3D carousel view in the Android 3.0 versions
+ of Google Books and YouTube or install the Renderscript sample applications that are shipped with
+ the SDK in <code>&lt;sdk_root&gt;/platforms/android-3.0/samples</code>.</p>
+
+ <h2 id="overview">Renderscript System Overview</h2>
+
+ <p>The Renderscript system adopts a control and slave architecture where the low-level native
+ code is controlled by the higher level Android system that runs in the virtual machine (VM). When
+ you use the Renderscript system, there are three layers of APIs that exist:</p>
+
+ <ul>
+ <li>The native Renderscript layer consists of the native Renderscript <code>.rs</code> files
+ that you write to compute mathematical operations, render graphics, or both. This layer does
+ the intensive computation or graphics rendering and returns the result back to the Android VM
+ through the reflected layer.</li>
+
+ <li>The reflected layer is a set of generated Android system classes (through reflection) based
+ on the native layer interface that you define. This layer acts as a bridge between the native
+ Renderscript layer and the Android system layer. The Android build tools automatically generate
+ the APIs for this layer during the build process.</li>
+
+ <li>The Android system layer consists of your normal Android APIs along with the Renderscript
+ APIs in {@link android.renderscript}. This layer handles things such as the Activity lifecycle
+ management of your application and calls the native Renderscript layer through the reflected
+ layer.</li>
+ </ul>
+
+ <p>To fully understand how the Renderscript system works, you must understand how the reflected
+ layer is generated and how it interacts with the native Renderscript layer and Android system
+ layer. The reflected layer provides the entry points into the native code, enabling the Android
+ system code to give high level commands like, "rotate the view" or "filter the bitmap." It
+ delegates all the heavy lifting to the native layer. To accomplish this, you need to create logic
+ to hook together all of these layers so that they can correctly communicate.</p>
+
+ <p>At the root of everything is your Renderscript, which is the actual C code that you write and
+ save to a <code>.rs</code> file in your project. There are two kinds of Renderscripts: compute
+ and graphics. A compute Renderscript does not do any graphics rendering while a graphics
+ Renderscript does.</p>
+
+ <p>When you create a Renderscript <code>.rs</code> file, an equivalent, reflective layer class,
+ {@link android.renderscript.ScriptC}, is generated by the build tools and exposes the native
+ functions to the Android system. This class is named
+ <code><em>ScriptC_renderscript_filename</em></code>. The following list describes the major
+ components of your native Renderscript code that is reflected:</p>
+
+ <ul>
+ <li>The non-static functions in your Renderscript (<code>.rs</code> file) are reflected into
+ <code><em>ScriptC_renderscript_filename</em></code> of type {@link
+ android.renderscript.ScriptC}.</li>
+
+ <li>Any non-static, global Renderscript variables are reflected into
+ <code><em>ScriptC_renderscript_filename</em></code>.
+ Accessor methods are generated, so the Android system layer can access the values.
+ The <code>get()</code> method comes with a one-way communication restriction.
+ The Android system layer always caches the last value that is set and returns that during a call to get.
+ If the native Renderscript code has changed the value, the change does propagate back to the Android system layer
+ for efficiency. If the global variables are initialized in the native Renderscript code, those values are used
+ to initialize the Android system versions. If global variables are marked as <code>const</code>,
+ then a <code>set()</code> method is not generated.
+ </li>
+
+ <li>Structs are reflected into their own classes, one for each struct, into a class named
+ <code>ScriptField_<em>struct_name</em></code> of type {@link
+ android.renderscript.Script.FieldBase}.</li>
+
+ <li>Global pointers have a special property. They provide attachment points where the Android system can attach allocations.
+ If the global pointer is a user defined structure type, it must be a type that is legal for reflection (primitives
+ or Renderscript data types). The Android system can call the reflected class to allocate memory and
+ optionally populate data, then attach it to the Renderscript.
+ For arrays of basic types, the procedure is similar, except a reflected class is not needed.
+ Renderscripts should not directly set the exported global pointers.</li>
+ </ul>
+
+ <p>The Android system also has a corresponding Renderscript context object, {@link
+ android.renderscript.RenderScript} (for a compute Renderscript) or {@link
+ android.renderscript.RenderScriptGL} (for a graphics Renderscript). This context object allows
+ you to bind to the reflected Renderscript class, so that the Renderscript context knows what its
+ corresponding native Renderscript is. If you have a graphics Renderscript context, you can also
+ specify a variety of Programs (stages in the graphics pipeline) to tweek how your graphics are
+ rendered. A graphics Renderscript context also needs a surface to render on, {@link
+ android.renderscript.RSSurfaceView}, which gets passed into its constructor. When all three of
+ the layers are connected, the Renderscript system can compute or render graphics.</p>
+
+ <h2 id="api">API overview</h2>
+
+ <p>Renderscript code is compiled and executed in a compact and well defined runtime, which has
+ access to a limited amount of functions. Renderscript cannot use the NDK or standard C functions,
+ because these functions are assumed to be running on a standard CPU. The Renderscript runtime
+ chooses the best processor to execute the code, which may not be the CPU, so it cannot guarantee
+ support for standard C libraries. What Renderscript does offer is an API that supports intensive
+ computation with an extensive collection of math APIs. Some key features of the Renderscript APIs
+ are:</p>
+
+
+ <h3 id="native-api">Native Renderscript APIs</h3>
+
+ <p>The Renderscript headers are located in the <code>include</code> and
+ <code>clang-include</code> directories in the
+ <code>&lt;sdk_root&gt;/platforms/android-3.0/renderscript</code> directory of the Android SDK.
+ The headers are automatically included for you, except for the graphics specific header,
+ which you can define as follows:</p>
+
+<pre>#include "rs_graphics.rsh"</pre>
+
+<p>Some key features of the native Renderscript libraries include:
+ <ul>
+ <li>A large collection of math functions with both scalar and vector typed overloaded versions
+ of many common routines. Operations such as adding, multiplying, dot product, and cross product
+ are available.</li>
+ <li>Conversion routines for primitive data types and vectors, matrix routines, date and time
+ routines, and graphics routines.</li>
+ <li>Logging functions</li>
+ <li>Graphics rendering functions</li>
+ <li>Memory allocation request features</li>
+ <li>Data types and structures to support the Renderscript system such as
+ Vector types for defining two-, three-, or four-vectors.</li></li>
+ </ul>
+ </ul>
+
+ <h3 id="reflective-api">Reflective layer APIs</h3>
+
+ <p>These classes are not generated by the reflection process, and are actually part of the
+ Android system APIs, but they are mainly used by the reflective layer classes to handle memory
+ allocation and management for your Renderscript. You normally do not need to be call these classes
+ directly.</p>
+
+ <p>Because of the constraints of the Renderscript native layer, you cannot do any dynamic
+ memory allocation in your Renderscript <code>.rs</code> file.
+ The native Renderscript layer can request memory from the Android system layer, which allocates memory
+ for you and does reference counting to figure out when to free the memory. A memory allocation
+ is taken care of by the {@link android.renderscript.Allocation} class and memory is requested
+ in your Renderscript code with the <code>the rs_allocation</code> type.
+ All references to Renderscript objects are counted, so when your Renderscript native code
+ or system code no longer references a particular {@link android.renderscript.Allocation}, it destroys itself.
+ Alternatively, you can call {@link android.renderscript.Allocation#destroy destroy()} from the
+ Android system level, which decreases the reference to the {@link android.renderscript.Allocation}.
+ If no references exist after the decrease, the {@link android.renderscript.Allocation} destroys itself.
+ The Android system object, which at this point is just an empty shell, is eventually garbage collected.
+ </p>
+
+ <p>The following classes are mainly used by the reflective layer classes:</p>
+
+ <table>
+ <tr>
+ <th>Android Object Type</th>
+
+ <th>Renderscript Native Type</th>
+
+ <th>Description</th>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.Element}</td>
+
+ <td>rs_element</td>
+
+ <td>
+ An {@link android.renderscript.Element} is the most basic element of a memory type. An
+ element represents one cell of a memory allocation. An element can have two forms: Basic or
+ Complex. They are typically created from C structures that are used within Renderscript
+ code and cannot contain pointers or nested arrays. The other common source of elements is
+ bitmap formats.
+
+ <p>A basic element contains a single component of data of any valid Renderscript data type.
+ Examples of basic element data types include a single float value, a float4 vector, or a
+ single RGB-565 color.</p>
+
+ <p>Complex elements contain a list of sub-elements and names that is basically a reflection
+ of a C struct. You access the sub-elements by name from a script or vertex program. The
+ most basic primitive type determines the data alignment of the structure. For example, a
+ float4 vector is alligned to <code>sizeof(float)</code> and not
+ <code>sizeof(float4)</code>. The ordering of the elements in memory are the order in which
+ they were added, with each component aligned as necessary.</p>
+ </td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.Type}</td>
+
+ <td>rs_type</td>
+
+ <td>A Type is an allocation template that consists of an element and one or more dimensions.
+ It describes the layout of the memory but does not allocate storage for the data that it
+ describes. A Type consists of five dimensions: X, Y, Z, LOD (level of detail), and Faces (of
+ a cube map). You can assign the X,Y,Z dimensions to any positive integer value within the
+ constraints of available memory. A single dimension allocation has an X dimension of greater
+ than zero while the Y and Z dimensions are zero to indicate not present. For example, an
+ allocation of x=10, y=1 is considered two dimensional and x=10, y=0 is considered one
+ dimensional. The LOD and Faces dimensions are booleans to indicate present or not
+ present.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.Allocation}</td>
+
+ <td>rs_allocation</td>
+
+ <td>
+ An {@link android.renderscript.Allocation} provides the memory for applications. An {@link
+ android.renderscript.Allocation} allocates memory based on a description of the memory that
+ is represented by a {@link android.renderscript.Type}. The {@link
+ android.renderscript.Type} describes an array of {@link android.renderscript.Element}s that
+ represent the memory to be allocated. Allocations are the primary way data moves into and
+ out of scripts.
+
+ <p>Memory is user-synchronized and it's possible for allocations to exist in multiple
+ memory spaces concurrently. For example, if you make a call to the graphics card to load a
+ bitmap, you give it the bitmap to load from in the system memory. After that call returns,
+ the graphics memory contains its own copy of the bitmap so you can choose whether or not to
+ maintain the bitmap in the system memory. If the Renderscript system modifies an allocation
+ that is used by other targets, it must call {@link android.renderscript#syncAll syncAll()} to push the updates to
+ the memory. Otherwise, the results are undefined.</p>
+
+ <p>Allocation data is uploaded in one of two primary ways: type checked and type unchecked.
+ For simple arrays there are <code>copyFrom()</code> functions that take an array from the
+ Android system code and copy it to the native layer memory store. Both type checked and
+ unchecked copies are provided. The unchecked variants allow the Android system to copy over
+ arrays of structures because it not support inherently support structures. For example, if
+ there is an allocation that is an array n floats, you can copy the data contained in a
+ float[n] array or a byte[n*4] array.</p>
+ </td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.Script}</td>
+
+ <td>rs_script</td>
+
+ <td>Renderscript scripts do much of the work in the native layer. This class is generated
+ from a Renderscript file that has the <code>.rs</code> file extension. This class is named
+ <code>ScriptC_<em>rendersript_filename</em></code> when it gets generated.</td>
+ </tr>
+ </table>
+
+ <h3 id="graphics-api">Graphics API</h3>
+
+ <p>Renderscript provides a number of graphics APIs for hardware-accelerated 3D rendering. The
+ Renderscript graphics APIs include a stateful context, {@link
+ android.renderscript.RenderScriptGL} that contains the current rendering state. The primary state
+ consists of the objects that are attached to the rendering context, which are the graphics Renderscript
+ and the four program types. The main working function of the graphics Renderscript is the code that is
+ defined in the <code>root()</code> function. The <code>root()</code> function is called each time the surface goes through a frame
+ refresh. The four program types mirror a traditional graphical rendering pipeline and are:</p>
+
+ <ul>
+ <li>Vertex</li>
+
+ <li>Fragment</li>
+
+ <li>Store</li>
+
+ <li>Raster</li>
+ </ul>
+
+ <p>Graphical scripts have more properties beyond a basic computational script, and they call the
+ 'rsg'-prefixed functions defined in the <code>rs_graphics.rsh</code> header file. A graphics
+ Renderscript can also set four pragmas that control the default bindings to the {@link
+ android.renderscript.RenderScriptGL} context when the script is executing:</p>
+
+ <ul>
+ <li>stateVertex</li>
+
+ <li>stateFragment</li>
+
+ <li>stateRaster</li>
+
+ <li>stateStore</li>
+ </ul>
+
+ <p>The possible values are <code>parent</code> or <code>default</code> for each pragma. Using
+ <code>default</code> says that when a script is executed, the bindings to the graphical context
+ are the system defaults. Using <code>parent</code> says that the state should be the same as it
+ is in the calling script. If this is a root script, the parent
+ state is taken from the bind points as set in the {@link android.renderscript.RenderScriptGL}
+ bind methods in the control environment (VM environment).</p>
+
+ <p>For example, you can define this at the top of your native Renderscript code:</p>
+ <pre>
+#pragma stateVertex(parent)
+#pragma stateStore(parent)
+</pre>
+
+ <p>The following table describes the major graphics specific APIs that are available to you:</p>
+
+ <table>
+ <tr>
+ <th>Android Object Type</th>
+
+ <th>Renderscript Native Type</th>
+
+ <th>Description</th>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.ProgramVertex}</td>
+
+ <td>rs_program_vertex</td>
+
+ <td>
+ The Renderscript vertex program, also known as a vertex shader, describes the stage in the
+ graphics pipeline responsible for manipulating geometric data in a user-defined way. The
+ object is constructed by providing Renderscript with the following data:
+
+ <ul>
+ <li>An Element describing its varying inputs or attributes</li>
+
+ <li>GLSL shader string that defines the body of the program</li>
+
+ <li>a Type that describes the layout of an Allocation containing constant or uniform
+ inputs</li>
+ </ul>
+
+ <p>Once the program is created, bind it to the graphics context. It is then used for all
+ subsequent draw calls until you bind a new program. If the program has constant inputs, the
+ user needs to bind an allocation containing those inputs. The allocation’s type must match
+ the one provided during creation. The Renderscript library then does all the necessary
+ plumbing to send those constants to the graphics hardware. Varying inputs to the shader,
+ such as position, normal, and texture coordinates are matched by name between the input
+ Element and the Mesh object being drawn. The signatures don’t have to be exact or in any
+ strict order. As long as the input name in the shader matches a channel name and size
+ available on the mesh, the run-time would take care of connecting the two. Unlike OpenGL,
+ there is no need to link the vertex and fragment programs.</p>
+ <p> To bind shader constructs to the Program, declare a struct containing the necessary shader constants in your native Renderscript code.
+ This struct is generated into a reflected class that you can use as a constant input element
+ during the Program's creation. It is an easy way to create an instance of this struct as an allocation.
+ You would then bind this Allocation to the Program and the Renderscript system sends the data that
+ is contained in the struct to the hardware when necessary. To update shader constants, you change the values
+ in the Allocation and notify the native Renderscript code of the change.</p>
+ </td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.ProgramFragment}</td>
+
+ <td>rs_program_fragment</td>
+
+ <td>The Renderscript fragment program, also known as the fragment shader, is responsible for
+ manipulating pixel data in a user-defined way. It’s constructed from a GLSL shader string
+ containing the program body, textures inputs, and a Type object describing the constants used
+ by the program. Like the vertex programs, when an allocation with constant input values is
+ bound to the shader, its values are sent to the graphics program automatically. Note that the
+ values inside the allocation are not explicitly tracked. If they change between two draw
+ calls using the same program object, notify the runtime of that change by calling
+ rsgAllocationSyncAll so it could send the new values to hardware. Communication between the
+ vertex and fragment programs is handled internally in the GLSL code. For example, if the
+ fragment program is expecting a varying input called varTex0, the GLSL code inside the
+ program vertex must provide it.
+ <p> To bind shader constructs to the this Program, declare a struct containing the necessary shader constants in your native Renderscript code.
+ This struct is generated into a reflected class that you can use as a constant input element
+ during the Program's creation. It is an easy way to create an instance of this struct as an allocation.
+ You would then bind this Allocation to the Program and the Renderscript system sends the data that
+ is contained in the struct to the hardware when necessary. To update shader constants, you change the values
+ in the Allocation and notify the native Renderscript code of the change.</p></td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.ProgramStore}</td>
+
+ <td>rs_program_store</td>
+
+ <td>The Renderscript ProgramStore contains a set of parameters that control how the graphics
+ hardware writes to the framebuffer. It could be used to enable/disable depth writes and
+ testing, setup various blending modes for effects like transparency and define write masks
+ for color components.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.ProgramRaster}</td>
+
+ <td>rs_program_raster</td>
+
+ <td>Program raster is primarily used to specify whether point sprites are enabled and to
+ control the culling mode. By default back faces are culled.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.Sampler}</td>
+
+ <td>rs_sampler</td>
+
+ <td>A Sampler object defines how data is extracted from textures. Samplers are bound to
+ Program objects (currently only a Fragment Program) alongside the texture whose sampling they
+ control. These objects are used to specify such things as edge clamping behavior, whether
+ mip-maps are used and the amount of anisotropy required. There may be situations where
+ hardware limitations prevent the exact behavior from being matched. In these cases, the
+ runtime attempts to provide the closest possible approximation. For example, the user
+ requested 16x anisotropy, but only 8x was set because it’s the best available on the
+ hardware.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.Mesh}</td>
+
+ <td>rs_mesh</td>
+
+ <td>A collection of allocations that represent vertex data (positions, normals, texture
+ coordinates) and index data such as triangles and lines. Vertex data can be interleaved
+ within one allocation, provided separately as multiple allocation objects, or done as a
+ combination of the above. The layout of these allocations will be extracted from their
+ Elements. When a vertex channel name matches an input in the vertex program, Renderscript
+ automatically connects the two. Moreover, even allocations that cannot be directly mapped to
+ graphics hardware can be stored as part of the mesh. Such allocations can be used as a
+ working area for vertex-related computation and will be ignored by the hardware. Parts of the
+ mesh could be rendered with either explicit index sets or primitive types.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.Font}</td>
+
+ <td>rs_font</td>
+
+ <td>
+ <p>This class gives you a way to draw hardware accelerated text. Internally, the glyphs are
+ rendered using the Freetype library, and an internal cache of rendered glyph bitmaps is
+ maintained. Each font object represents a combination of a typeface and point sizes.
+ Multiple font objects can be created to represent faces such as bold and italic and to
+ create different font sizes. During creation, the framework determines the device screen's
+ DPI to ensure proper sizing across multiple configurations.</p>
+
+ <p>Font rendering can impact performance. Even though though the state changes are
+ transparent to the user, they are happening internally. It is more efficient to render
+ large batches of text in sequence, and it is also more efficient to render multiple
+ characters at once instead of one by one.</p>
+
+ <p>Font color and transparency are not part of the font object and can be freely modified
+ in the script to suit the your needs. Font colors work as a state machine, and every new
+ call to draw text will use the last color set in the script.</p>
+ </td>
+ </tr>
+ </table>
+
+
+ <h2 id="developing">Developing a Renderscript application</h2>
+
+ <p>The basic workflow of developing a Renderscript application is:</p>
+
+ <ol>
+ <li>Analyze your application's requirements and figure out what you want to develop with
+ Renderscript. To take full advantage of Renderscript, you want to use it when the computation
+ or graphics performance you're getting with the normal Android system APIs is
+ insufficient.</li>
+
+ <li>Design the interface of your Renderscript code and implement it using the native
+ Renderscript APIs that are included in the Android SDK in
+ <code>&lt;sdk_root&gt;/platforms/android-3.0/renderscript</code>.</li>
+
+ <li>Create an Android project as you would normally, in Eclipse or with the
+ <code>android</code> tool.</li>
+
+ <li>Place your Renderscript files in <code>src</code> folder of the Android project so that the
+ build tools can generate the reflective layer classes.</li>
+
+ <li>Create your application, calling the Renderscript through the reflected class layer when
+ you need to.</li>
+
+ <li>Build, install, and run your application as you would normally.</li>
+ </ol>
+
+ <p>To see how a simple Renderscript application is put together, see <a href="#hello-world">The
+ Hello World Renderscript Graphics Application</a>. The SDK also ships with many Renderscript
+ samples in the<code>&lt;sdk_root&gt;/samples/android-3.0/</code> directory.</p>
+
+ <h3 id="hello-graphics">The Hello Graphics Application</h3>
+
+ <p>This small application demonstrates the structure of a simple Renderscript application. You
+ can model your Renderscript application after the basic structure of this application. You can
+ find the complete source in the SDK in the
+ <code>&lt;android-sdk&gt;/platforms/android-3.0/samples/HelloWorldRS directory</code>. The
+ application uses Renderscript to draw the string, "Hello World!" to the screen and redraws the
+ text whenever the user touches the screen at the location of the touch. This application is only
+ a demonstration and you should not use the Renderscript system to do something this trivial. The
+ application contains the following source files:</p>
+
+ <ul>
+ <li><code>HelloWorld</code>: The main Activity for the application. This class is present to
+ provide Activity lifecycle management. It mainly delegates work to HelloWorldView, which is the
+ Renderscript surface that the sample actually draws on.</li>
+
+ <li><code>HelloWorldView</code>: The Renderscript surface that the graphics render on. If you
+ are using Renderscript for graphics rendering, you must have a surface to render on. If you are
+ using it for computatational operations only, then you do not need this.</li>
+
+ <li><code>HelloWorldRS</code>: The class that calls the native Renderscript code through high
+ level entry points that are generated by the Android build tools.</li>
+
+ <li><code>helloworld.rs</code>: The Renderscript native code that draws the text on the
+ screen.</li>
+
+ <li>
+ <p>The <code>&lt;project_root&gt;/gen</code> directory contains the reflective layer classes
+ that are generated by the Android build tools. You will notice a
+ <code>ScriptC_helloworld</code> class, which is the reflective version of the Renderscript
+ and contains the entry points into the <code>helloworld.rs</code> native code. This file does
+ not appear until you run a build.</p>
+ </li>
+ </ul>
+
+ <p>Each file has its own distinct use. The following section demonstrates in detail how the
+ sample works:</p>
+
+ <dl>
+ <dt><code>helloworld.rs</code></dt>
+
+ <dd>
+ The native Renderscript code is contained in the <code>helloworld.rs</code> file. Every
+ <code>.rs</code> file must contain two pragmas that define the version of Renderscript
+ that it is using (1 is the only version for now), and the package name that the reflected
+ classes should be generated with. For example:
+<pre>
+#pragma version(1)
+
+#pragma rs java_package_name(com.my.package.name)
+</pre>
+ <p>An <code>.rs</code> file can also declare two special functions:</p>
+
+ <ul>
+ <li>
+ <code>init()</code>: This function is called once for each instance of this Renderscript
+ file that is loaded on the device, before the script is accessed in any other way by the
+ Renderscript system. The <code>init()</code> is ideal for doing one time setup after the
+ machine code is loaded such as initializing complex constant tables. The
+ <code>init()</code> function for the <code>helloworld.rs</code> script sets the initial
+ location of the text that is rendered to the screen:
+ <pre>
+void init(){
+ gTouchX = 50.0f;
+ gTouchY = 50.0f;
+}
+</pre>
+ </li>
+
+ <li>
+ <code>root()</code>: This function is the default worker function for this Renderscript
+ file. For graphics Renderscript applications, like this one, the Renderscript system
+ expects this function to render the frame that is going to be displayed. It is called
+ every time the frame refreshes. The <code>root()</code> function for the
+ <code>helloworld.rs</code> script sets the background color of the frame, the color of
+ the text, and then draws the text where the user last touched the screen:
+<pre>
+int root(int launchID) {
+ // Clear the background color
+ rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ // Tell the runtime what the font color should be
+ rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+ // Introduce ourselves to the world by drawing a greeting
+ // at the position that the user touched on the screen
+ rsgDrawText("Hello World!", gTouchX, gTouchY);
+
+ // Return value tells RS roughly how often to redraw
+ // in this case 20 ms
+ return 20;
+}
+</pre>
+
+ <p>The return value, <code>20</code>, is the desired frame refresh rate in milliseconds.
+ The real screen refresh rate depends on the hardware, computation, and rendering
+ complexity that the <code>root()</code> function has to execute. A value of
+ <code>0</code> tells the screen to render only once and to only render again when a
+ change has been made to one of the properties that are being modified by the Renderscript
+ code.</p>
+
+ <p>Besides the <code>init()</code> and <code>root()</code> functions, you can define the
+ other native functions, structs, data types, and any other logic for your Renderscript.
+ You can even define separate header files as <code>.rsh</code> files.</p>
+ </li>
+ </ul>
+ </dd>
+
+ <dt><code>ScriptC_helloworld</code></dt>
+
+ <dd>This class is generated by the Android build tools and is the reflected version of the
+ <code>helloworld.rs</code> Renderscript. It provides a a high level entry point into the
+ <code>helloworld.rs</code> native code by defining the corresponding methods that you can call
+ from Android system APIs.</dd>
+
+ <dt><code>helloworld.bc</code> bytecode</dt>
+
+ <dd>This file is the intermediate, platform-independent bytecode that gets compiled on the
+ device when the Renderscript application runs. It is generated by the Android build tools and
+ is packaged with the <code>.apk</code> file and subsequently compiled on the device at runtime.
+ This file is located in the <code>&lt;project_root&gt;/res/raw/</code> directory and is named
+ <code>rs_filename.bc</code>. You need to bind these files to your Renderscript context before
+ call any Renderscript code from your Android application. You can reference them in your code
+ with <code>R.id.rs_filename</code>.</dd>
+
+ <dt><code>HelloWorldView</code> class</dt>
+
+ <dd>
+ This class represents the Surface View that the Renderscript graphics are drawn on. It does
+ some administrative tasks in the <code>ensureRenderScript()</code> method that sets up the
+ Renderscript system. This method creates a {@link android.renderscript.RenderScriptGL}
+ object, which represents the context of the Renderscript and creates a default surface to
+ draw on (you can set the surface properties such as alpha and bit depth in the {@link
+ android.renderscript.RenderScriptGL.SurfaceConfig} class ). When a {@link
+ android.renderscript.RenderScriptGL} is instantiated, this class calls the
+ <code>HelloRS</code> class and creates the instance of the actual Renderscript graphics
+ renderer.
+ <pre>
+// Renderscipt context
+private RenderScriptGL mRS;
+// Script that does the rendering
+private HelloWorldRS mRender;
+
+ private void ensureRenderScript() {
+ if (mRS == null) {
+ // Initialize Renderscript with desired surface characteristics.
+ // In this case, just use the defaults
+ RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+ mRS = createRenderScriptGL(sc);
+
+ // Create an instance of the Renderscript that does the rendering
+ mRender = new HelloWorldRS();
+ mRender.init(mRS, getResources());
+ }
+ }
+</pre>
+
+ <p>This class also handles the important lifecycle events and relays touch events to the
+ Renderscript renderer. When a user touches the screen, it calls the renderer,
+ <code>HelloWorldRS</code> and asks it to draw the text on the screen at the new location.</p>
+ <pre>
+public boolean onTouchEvent(MotionEvent ev) {
+ // Pass touch events from the system to the rendering script
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mRender.onActionDown((int)ev.getX(), (int)ev.getY());
+ return true;
+ }
+ return false;
+}
+</pre>
+ </dd>
+
+ <dt><code>HelloWorldRS</code></dt>
+
+ <dd>
+ This class represents the Renderscript renderer for the <code>HelloWorldView</code> Surface
+ View. It interacts with the native Renderscript code that is defined in
+ <code>helloworld.rs</code> through the interfaces exposed by <code>ScriptC_helloworld</code>.
+ To be able to call the native code, it creates an instance of the Renderscript reflected
+ class, <code>ScriptC_helloworld</code>. The reflected Renderscript object binds the
+ Renderscript bytecode (<code>R.raw.helloworld</code>) and the Renderscript context, {@link
+ android.renderscript.RenderScriptGL}, so the context knows to use the right Renderscript to
+ render its surface.
+ <pre>
+private Resources mRes;
+private RenderScriptGL mRS;
+private ScriptC_helloworld mScript;
+
+private void initRS() {
+ mScript = new ScriptC_helloworld(mRS, mRes, R.raw.helloworld);
+ mRS.bindRootScript(mScript);
+}
+</pre>
+ </dd>
+ </dl> \ No newline at end of file
diff --git a/docs/html/guide/topics/graphics/view-animation.jd b/docs/html/guide/topics/graphics/view-animation.jd
new file mode 100644
index 000000000000..ad27e1ce18ac
--- /dev/null
+++ b/docs/html/guide/topics/graphics/view-animation.jd
@@ -0,0 +1,190 @@
+page.title=View Animation
+@jd:body
+
+ <div id="qv-wrapper">
+ <div id="qv">
+ <h2>In this document</h2>
+
+ <ol>
+ <li><a href="#tween-animation">Tween animation</a></li>
+ <li><a href="#frame-animation">Frame animation</a></li>
+ </ol>
+
+ </div>
+ </div>
+
+ You can use View Animation in any View object to
+ perform tweened animation and frame by frame animation. Tween animation calculates the animation
+ given information such as the start point, end point, size, rotation, and other common aspects of
+ an animation. Frame by frame animation lets you load a series of Drawable resources one after
+ another to create an animation.
+
+ <h2 id="tween-animation">Tween Animation</h2>
+
+ <p>A tween animation can perform a series of simple transformations (position, size, rotation,
+ and transparency) on the contents of a View object. So, if you have a {@link
+ android.widget.TextView} object, you can move, rotate, grow, or shrink the text. If it has a
+ background image, the background image will be transformed along with the text. The {@link
+ android.view.animation animation package} provides all the classes used in a tween animation.</p>
+
+ <p>A sequence of animation instructions defines the tween animation, defined by either XML or
+ Android code. As with defining a layout, an XML file is recommended because it's more readable,
+ reusable, and swappable than hard-coding the animation. In the example below, we use XML. (To
+ learn more about defining an animation in your application code, instead of XML, refer to the
+ {@link android.view.animation.AnimationSet} class and other {@link
+ android.view.animation.Animation} subclasses.)</p>
+
+ <p>The animation instructions define the transformations that you want to occur, when they will
+ occur, and how long they should take to apply. Transformations can be sequential or simultaneous
+ - for example, you can have the contents of a TextView move from left to right, and then rotate
+ 180 degrees, or you can have the text move and rotate simultaneously. Each transformation takes a
+ set of parameters specific for that transformation (starting size and ending size for size
+ change, starting angle and ending angle for rotation, and so on), and also a set of common
+ parameters (for instance, start time and duration). To make several transformations happen
+ simultaneously, give them the same start time; to make them sequential, calculate the start time
+ plus the duration of the preceding transformation.</p>
+
+ <p>The animation XML file belongs in the <code>res/anim/</code> directory of your Android
+ project. The file must have a single root element: this will be either a single
+ <code>&lt;alpha&gt;</code>, <code>&lt;scale&gt;</code>, <code>&lt;translate&gt;</code>,
+ <code>&lt;rotate&gt;</code>, interpolator element, or <code>&lt;set&gt;</code> element that holds
+ groups of these elements (which may include another <code>&lt;set&gt;</code>). By default, all
+ animation instructions are applied simultaneously. To make them occur sequentially, you must
+ specify the <code>startOffset</code> attribute, as shown in the example below.</p>
+
+ <p>The following XML from one of the ApiDemos is used to stretch, then simultaneously spin and
+ rotate a View object.</p>
+ <pre>
+&lt;set android:shareInterpolator="false"&gt;
+ &lt;scale
+ android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+ android:fromXScale="1.0"
+ android:toXScale="1.4"
+ android:fromYScale="1.0"
+ android:toYScale="0.6"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillAfter="false"
+ android:duration="700" /&gt;
+ &lt;set android:interpolator="@android:anim/decelerate_interpolator"&gt;
+ &lt;scale
+ android:fromXScale="1.4"
+ android:toXScale="0.0"
+ android:fromYScale="0.6"
+ android:toYScale="0.0"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:startOffset="700"
+ android:duration="400"
+ android:fillBefore="false" /&gt;
+ &lt;rotate
+ android:fromDegrees="0"
+ android:toDegrees="-45"
+ android:toYScale="0.0"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:startOffset="700"
+ android:duration="400" /&gt;
+ &lt;/set&gt;
+&lt;/set&gt;
+</pre>
+
+ <p>Screen coordinates (not used in this example) are (0,0) at the upper left hand corner, and
+ increase as you go down and to the right.</p>
+
+ <p>Some values, such as pivotX, can be specified relative to the object itself or relative to the
+ parent. Be sure to use the proper format for what you want ("50" for 50% relative to the parent,
+ or "50%" for 50% relative to itself).</p>
+
+ <p>You can determine how a transformation is applied over time by assigning an {@link
+ android.view.animation.Interpolator}. Android includes several Interpolator subclasses that
+ specify various speed curves: for instance, {@link android.view.animation.AccelerateInterpolator}
+ tells a transformation to start slow and speed up. Each one has an attribute value that can be
+ applied in the XML.</p>
+
+ <p>With this XML saved as <code>hyperspace_jump.xml</code> in the <code>res/anim/</code>
+ directory of the project, the following code will reference it and apply it to an {@link
+ android.widget.ImageView} object from the layout.</p>
+ <pre>
+ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
+Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
+spaceshipImage.startAnimation(hyperspaceJumpAnimation);
+</pre>
+
+ <p>As an alternative to <code>startAnimation()</code>, you can define a starting time for the
+ animation with <code>{@link android.view.animation.Animation#setStartTime(long)
+ Animation.setStartTime()}</code>, then assign the animation to the View with <code>{@link
+ android.view.View#setAnimation(android.view.animation.Animation) View.setAnimation()}</code>.</p>
+
+ <p>For more information on the XML syntax, available tags and attributes, see <a href=
+ "{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
+
+ <p class="note"><strong>Note:</strong> Regardless of how your animation may move or resize, the
+ bounds of the View that holds your animation will not automatically adjust to accommodate it.
+ Even so, the animation will still be drawn beyond the bounds of its View and will not be clipped.
+ However, clipping <em>will occur</em> if the animation exceeds the bounds of the parent View.</p>
+
+ <h2 id="frame-animation">Frame Animation</h2>
+
+ <p>This is a traditional animation in the sense that it is created with a sequence of different
+ images, played in order, like a roll of film. The {@link
+ android.graphics.drawable.AnimationDrawable} class is the basis for frame animations.</p>
+
+ <p>While you can define the frames of an animation in your code, using the {@link
+ android.graphics.drawable.AnimationDrawable} class API, it's more simply accomplished with a
+ single XML file that lists the frames that compose the animation. Like the tween animation above,
+ the XML file for this kind of animation belongs in the <code>res/drawable/</code> directory of
+ your Android project. In this case, the instructions are the order and duration for each frame of
+ the animation.</p>
+
+ <p>The XML file consists of an <code>&lt;animation-list&gt;</code> element as the root node and a
+ series of child <code>&lt;item&gt;</code> nodes that each define a frame: a drawable resource for
+ the frame and the frame duration. Here's an example XML file for a frame-by-frame animation:</p>
+ <pre>
+&lt;animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+ android:oneshot="true"&gt;
+ &lt;item android:drawable="@drawable/rocket_thrust1" android:duration="200" /&gt;
+ &lt;item android:drawable="@drawable/rocket_thrust2" android:duration="200" /&gt;
+ &lt;item android:drawable="@drawable/rocket_thrust3" android:duration="200" /&gt;
+&lt;/animation-list&gt;
+</pre>
+
+ <p>This animation runs for just three frames. By setting the <code>android:oneshot</code>
+ attribute of the list to <var>true</var>, it will cycle just once then stop and hold on the last
+ frame. If it is set <var>false</var> then the animation will loop. With this XML saved as
+ <code>rocket_thrust.xml</code> in the <code>res/drawable/</code> directory of the project, it can
+ be added as the background image to a View and then called to play. Here's an example Activity,
+ in which the animation is added to an {@link android.widget.ImageView} and then animated when the
+ screen is touched:</p>
+ <pre>
+AnimationDrawable rocketAnimation;
+
+public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
+ rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
+ rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
+}
+
+public boolean onTouchEvent(MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ rocketAnimation.start();
+ return true;
+ }
+ return super.onTouchEvent(event);
+}
+</pre>
+
+ <p>It's important to note that the <code>start()</code> method called on the AnimationDrawable
+ cannot be called during the <code>onCreate()</code> method of your Activity, because the
+ AnimationDrawable is not yet fully attached to the window. If you want to play the animation
+ immediately, without requiring interaction, then you might want to call it from the <code>{@link
+ android.app.Activity#onWindowFocusChanged(boolean) onWindowFocusChanged()}</code> method in your
+ Activity, which will get called when Android brings your window into focus.</p>
+
+ <p>For more information on the XML syntax, available tags and attributes, see <a href=
+ "{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
+</body>
+</html>
diff --git a/docs/html/guide/topics/media/index.jd b/docs/html/guide/topics/media/index.jd
index e355212c9af8..b6d162917ca8 100644
--- a/docs/html/guide/topics/media/index.jd
+++ b/docs/html/guide/topics/media/index.jd
@@ -148,70 +148,209 @@ myJet.play();
<h2 id="capture">Audio Capture</h2>
<p>Audio capture from the device is a bit more complicated than audio/video playback, but still fairly simple:</p>
<ol>
- <li>Create a new instance of {@link android.media.MediaRecorder
- android.media.MediaRecorder} using <code>new</code></li>
- <li>Create a new instance of {@link android.content.ContentValues
- android.content.ContentValues} and put in some standard properties like
- <code>TITLE</code>, <code>TIMESTAMP</code>, and the all important
- <code>MIME_TYPE</code></li>
- <li>Create a file path for the data to go to (you can use {@link
- android.content.ContentResolver android.content.ContentResolver} to
- create an entry in the Content database and get it to assign a path
- automatically which you can then use)</li>
- <li>Set the audio source using {@link android.media.MediaRecorder#setAudioSource
- MediaRecorder.setAudioSource()}. You will probably want to use
+ <li>Create a new instance of {@link android.media.MediaRecorder android.media.MediaRecorder} using <code>new</code></li>
+ <li>Set the audio source using
+ {@link android.media.MediaRecorder#setAudioSource MediaRecorder.setAudioSource()}. You will probably want to use
<code>MediaRecorder.AudioSource.MIC</code></li>
- <li>Set output file format using {@link
- android.media.MediaRecorder#setOutputFormat MediaRecorder.setOutputFormat()}
+ <li>Set output file format using
+ {@link android.media.MediaRecorder#setOutputFormat MediaRecorder.setOutputFormat()}
+ </li>
+ <li>Set output file name using
+ {@link android.media.MediaRecorder#setOutputFile MediaRecorder.setOutputFile()}
</li>
<li>Set the audio encoder using
{@link android.media.MediaRecorder#setAudioEncoder MediaRecorder.setAudioEncoder()}
</li>
- <li>Call {@link android.media.MediaRecorder#prepare prepare()}
+ <li>Call {@link android.media.MediaRecorder#prepare MediaRecorder.prepare()}
on the MediaRecorder instance.</li>
<li>To start audio capture, call
- {@link android.media.MediaRecorder#start start()}. </li>
- <li>To stop audio capture, call {@link android.media.MediaRecorder#stop stop()}.
+ {@link android.media.MediaRecorder#start MediaRecorder.start()}. </li>
+ <li>To stop audio capture, call {@link android.media.MediaRecorder#stop MediaRecorder.stop()}.
<li>When you are done with the MediaRecorder instance, call
-{@link android.media.MediaRecorder#release release()} on it. </li>
+{@link android.media.MediaRecorder#release MediaRecorder.release()} on it. Calling
+{@link android.media.MediaRecorder#release MediaRecorder.release()} is always recommended to
+free the resource immediately.</li>
</ol>
-<h3>Example: Audio Capture Setup and Start</h3>
-<p>The example below illustrates how to set up, then start audio capture.</p>
+<h3>Example: Record audio and play the recorded audio</h3>
+<p>The example class below illustrates how to set up, start and stop audio capture, and to play the recorded audio file.</p>
<pre>
- recorder = new MediaRecorder();
- ContentValues values = new ContentValues(3);
-
- values.put(MediaStore.MediaColumns.TITLE, SOME_NAME_HERE);
- values.put(MediaStore.MediaColumns.TIMESTAMP, System.currentTimeMillis());
- values.put(MediaStore.MediaColumns.MIME_TYPE, recorder.getMimeContentType());
-
- ContentResolver contentResolver = new ContentResolver();
-
- Uri base = MediaStore.Audio.INTERNAL_CONTENT_URI;
- Uri newUri = contentResolver.insert(base, values);
-
- if (newUri == null) {
- // need to handle exception here - we were not able to create a new
- // content entry
+/*
+ * The application needs to have the permission to write to external storage
+ * if the output file is written to the external storage, and also the
+ * permission to record audio. These permissions must be set in the
+ * application's AndroidManifest.xml file, with something like:
+ *
+ * &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&gt;
+ * &lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
+ *
+ */
+package com.android.audiorecordtest;
+
+import android.app.Activity;
+import android.widget.LinearLayout;
+import android.os.Bundle;
+import android.os.Environment;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.content.Context;
+import android.util.Log;
+import android.media.MediaRecorder;
+import android.media.MediaPlayer;
+
+import java.io.IOException;
+
+
+public class AudioRecordTest extends Activity
+{
+ private static final String LOG_TAG = "AudioRecordTest";
+ private static String mFileName = null;
+
+ private RecordButton mRecordButton = null;
+ private MediaRecorder mRecorder = null;
+
+ private PlayButton mPlayButton = null;
+ private MediaPlayer mPlayer = null;
+
+ private void onRecord(boolean start) {
+ if (start) {
+ startRecording();
+ } else {
+ stopRecording();
+ }
}
-
- String path = contentResolver.getDataFilePath(newUri);
-
- // could use setPreviewDisplay() to display a preview to suitable View here
-
- recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- recorder.setOutputFile(path);
-
- recorder.prepare();
- recorder.start();
-</pre>
-<h3>Stop Recording</h3>
-<p>Based on the example above, here's how you would stop audio capture. </p>
-<pre>
- recorder.stop();
- recorder.release();
+
+ private void onPlay(boolean start) {
+ if (start) {
+ startPlaying();
+ } else {
+ stopPlaying();
+ }
+ }
+
+ private void startPlaying() {
+ mPlayer = new MediaPlayer();
+ try {
+ mPlayer.setDataSource(mFileName);
+ mPlayer.prepare();
+ mPlayer.start();
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "prepare() failed");
+ }
+ }
+
+ private void stopPlaying() {
+ mPlayer.release();
+ mPlayer = null;
+ }
+
+ private void startRecording() {
+ mRecorder = new MediaRecorder();
+ mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+ mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+ mRecorder.setOutputFile(mFileName);
+ mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+
+ try {
+ mRecorder.prepare();
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "prepare() failed");
+ }
+
+ mRecorder.start();
+ }
+
+ private void stopRecording() {
+ mRecorder.stop();
+ mRecorder.release();
+ mRecorder = null;
+ }
+
+ class RecordButton extends Button {
+ boolean mStartRecording = true;
+
+ OnClickListener clicker = new OnClickListener() {
+ public void onClick(View v) {
+ onRecord(mStartRecording);
+ if (mStartRecording) {
+ setText("Stop recording");
+ } else {
+ setText("Start recording");
+ }
+ mStartRecording = !mStartRecording;
+ }
+ };
+
+ public RecordButton(Context ctx) {
+ super(ctx);
+ setText("Start recording");
+ setOnClickListener(clicker);
+ }
+ }
+
+ class PlayButton extends Button {
+ boolean mStartPlaying = true;
+
+ OnClickListener clicker = new OnClickListener() {
+ public void onClick(View v) {
+ onPlay(mStartPlaying);
+ if (mStartPlaying) {
+ setText("Stop playing");
+ } else {
+ setText("Start playing");
+ }
+ mStartPlaying = !mStartPlaying;
+ }
+ };
+
+ public PlayButton(Context ctx) {
+ super(ctx);
+ setText("Start playing");
+ setOnClickListener(clicker);
+ }
+ }
+
+ public AudioRecordTest() {
+ mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
+ mFileName += "/audiorecordtest.3gp";
+ }
+
+ &#64;Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ LinearLayout ll = new LinearLayout(this);
+ mRecordButton = new RecordButton(this);
+ ll.addView(mRecordButton,
+ new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ 0));
+ mPlayButton = new PlayButton(this);
+ ll.addView(mPlayButton,
+ new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ 0));
+ setContentView(ll);
+ }
+
+ &#64;Override
+ public void onPause() {
+ super.onPause();
+ if (mRecorder != null) {
+ mRecorder.release();
+ mRecorder = null;
+ }
+
+ if (mPlayer != null) {
+ mPlayer.release();
+ mPlayer = null;
+ }
+ }
+}
</pre>
+
diff --git a/docs/html/images/animation/animation-linear.png b/docs/html/images/animation/animation-linear.png
new file mode 100644
index 000000000000..08bd9fc3dc2c
--- /dev/null
+++ b/docs/html/images/animation/animation-linear.png
Binary files differ
diff --git a/docs/html/images/animation/animation-nonlinear.png b/docs/html/images/animation/animation-nonlinear.png
new file mode 100644
index 000000000000..31c17120b551
--- /dev/null
+++ b/docs/html/images/animation/animation-nonlinear.png
Binary files differ
diff --git a/docs/html/images/animation/valueanimator.png b/docs/html/images/animation/valueanimator.png
new file mode 100644
index 000000000000..6cc2a13bbfca
--- /dev/null
+++ b/docs/html/images/animation/valueanimator.png
Binary files differ
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index 9cd0efe66f2c..1ba5beb34843 100755
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -444,7 +444,7 @@ static void jniPreviewProgressCallback (void* cookie, M4OSA_UInt32 msgType,
pContext->mOverlayRenderingMode = pContext->pEditSettings->\
pClipList[pCurrEditInfo->clipIndex]->xVSS.MediaRendering;
- LOGI("rendering mode %d ", pContext->mOverlayRenderingMode);
+ LOGV("rendering mode %d ", pContext->mOverlayRenderingMode);
}
@@ -653,7 +653,7 @@ static int videoEditor_renderPreviewFrame(JNIEnv* pEnv,
}
for (i = 0; i < uiNumberOfClipsInStoryBoard; i++) {
- if (timeMs < (iIncrementedDuration +
+ if (timeMs <= (iIncrementedDuration +
(pContext->pEditSettings->pClipList[i]->uiEndCutTime -
pContext->pEditSettings->pClipList[i]->uiBeginCutTime)))
{
@@ -696,6 +696,7 @@ static int videoEditor_renderPreviewFrame(JNIEnv* pEnv,
pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoHeight,
pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoWidth,
(M4OSA_Void **)&frameStr.pBuffer);
+ tnTimeMs = (M4OSA_UInt32)timeMs;
} else {
/* Handle 3gp/mp4 Clips here */
/* get thumbnail*/
@@ -1482,6 +1483,7 @@ videoEditor_populateSettings(
int nbOverlays = 0;
int i,j = 0;
int *pOverlayIndex = M4OSA_NULL;
+ M4OSA_Char* pTempChar = M4OSA_NULL;
// Add a code marker (the condition must always be true).
ADD_CODE_MARKER_FUN(NULL != pEnv)
@@ -1809,20 +1811,63 @@ videoEditor_populateSettings(
pContext->mAudioSettings->fileType
= pEnv->GetIntField(audioSettingObject,fid);
M4OSA_TRACE1_1("fileType = %d",pContext->mAudioSettings->fileType);
+
+ /* free previous allocations , if any */
+ if (pContext->mAudioSettings->pFile != NULL) {
+ M4OSA_free((M4OSA_MemAddr32)pContext->mAudioSettings->pFile);
+ pContext->mAudioSettings->pFile = M4OSA_NULL;
+ }
+ if (pContext->mAudioSettings->pPCMFilePath != NULL) {
+ M4OSA_free((M4OSA_MemAddr32)pContext->mAudioSettings->pPCMFilePath);
+ pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL;
+ }
+
fid = pEnv->GetFieldID(audioSettingClazz,"pFile","Ljava/lang/String;");
strPath = (jstring)pEnv->GetObjectField(audioSettingObject,fid);
- pContext->mAudioSettings->pFile
- = (M4OSA_Char*)pEnv->GetStringUTFChars(strPath, M4OSA_NULL);
+ pTempChar = (M4OSA_Char*)pEnv->GetStringUTFChars(strPath, M4OSA_NULL);
+ if (pTempChar != NULL) {
+ pContext->mAudioSettings->pFile = (M4OSA_Char*) M4OSA_malloc(
+ (M4OSA_UInt32)(strlen((const char*)pTempChar))+1 /* +1 for NULL termination */, 0,
+ (M4OSA_Char*)"strPath allocation " );
+ if (pContext->mAudioSettings->pFile != M4OSA_NULL) {
+ M4OSA_memcpy((M4OSA_Int8 *)pContext->mAudioSettings->pFile ,
+ (M4OSA_Int8 *)pTempChar , strlen((const char*)pTempChar));
+ ((M4OSA_Int8 *)(pContext->mAudioSettings->pFile))[strlen((const char*)pTempChar)] = '\0';
+ pEnv->ReleaseStringUTFChars(strPath,(const char *)pTempChar);
+ } else {
+ pEnv->ReleaseStringUTFChars(strPath,(const char *)pTempChar);
+ VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR",
+ "regenerateAudio() Malloc failed for pContext->mAudioSettings->pFile ");
+ videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
+ M4OSA_TRUE, M4ERR_ALLOC);
+ goto videoEditor_populateSettings_cleanup;
+ }
+ }
M4OSA_TRACE1_1("file name = %s",pContext->mAudioSettings->pFile);
VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "regenerateAudio() file name = %s",\
pContext->mAudioSettings->pFile);
fid = pEnv->GetFieldID(audioSettingClazz,"pcmFilePath","Ljava/lang/String;");
strPCMPath = (jstring)pEnv->GetObjectField(audioSettingObject,fid);
-
- pContext->mAudioSettings->pPCMFilePath =
- (M4OSA_Char*)pEnv->GetStringUTFChars(strPCMPath, M4OSA_NULL);
-
+ pTempChar = (M4OSA_Char*)pEnv->GetStringUTFChars(strPCMPath, M4OSA_NULL);
+ if (pTempChar != NULL) {
+ pContext->mAudioSettings->pPCMFilePath = (M4OSA_Char*) M4OSA_malloc(
+ (M4OSA_UInt32)(strlen((const char*)pTempChar))+1 /* +1 for NULL termination */, 0,
+ (M4OSA_Char*)"strPCMPath allocation " );
+ if (pContext->mAudioSettings->pPCMFilePath != M4OSA_NULL) {
+ M4OSA_memcpy((M4OSA_Int8 *)pContext->mAudioSettings->pPCMFilePath ,
+ (M4OSA_Int8 *)pTempChar , strlen((const char*)pTempChar));
+ ((M4OSA_Int8 *)(pContext->mAudioSettings->pPCMFilePath))[strlen((const char*)pTempChar)] = '\0';
+ pEnv->ReleaseStringUTFChars(strPCMPath,(const char *)pTempChar);
+ } else {
+ pEnv->ReleaseStringUTFChars(strPCMPath,(const char *)pTempChar);
+ VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR",
+ "regenerateAudio() Malloc failed for pContext->mAudioSettings->pPCMFilePath ");
+ videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
+ M4OSA_TRUE, M4ERR_ALLOC);
+ goto videoEditor_populateSettings_cleanup;
+ }
+ }
VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "pPCMFilePath -- %s ",\
pContext->mAudioSettings->pPCMFilePath);
@@ -1849,15 +1894,6 @@ videoEditor_populateSettings(
pEnv->SetBooleanField(thiz,fid,regenerateAudio);
}
- if (strPath != NULL) {
- pEnv->ReleaseStringUTFChars(strPath,
- (const char *)pContext->mAudioSettings->pFile);
- }
- if (strPCMPath != NULL) {
- pEnv->ReleaseStringUTFChars(strPCMPath,
- (const char *)pContext->mAudioSettings->pPCMFilePath);
- }
-
/* Audio mix and duck */
fid = pEnv->GetFieldID(audioSettingClazz,"ducking_threshold","I");
pContext->mAudioSettings->uiInDucking_threshold
@@ -1882,6 +1918,7 @@ videoEditor_populateSettings(
} else {
if (pContext->mAudioSettings != M4OSA_NULL) {
pContext->mAudioSettings->pFile = M4OSA_NULL;
+ pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL;
pContext->mAudioSettings->bRemoveOriginal = 0;
pContext->mAudioSettings->uiNbChannels = 0;
pContext->mAudioSettings->uiSamplingFrequency = 0;
@@ -1890,7 +1927,7 @@ videoEditor_populateSettings(
pContext->mAudioSettings->uiAddVolume = 0;
pContext->mAudioSettings->beginCutMs = 0;
pContext->mAudioSettings->endCutMs = 0;
- pContext->mAudioSettings->fileType = 0;
+ pContext->mAudioSettings->fileType = 0;
pContext->mAudioSettings->bLoop = 0;
pContext->mAudioSettings->uiInDucking_lowVolume = 0;
pContext->mAudioSettings->bInDucking_enable = 0;
@@ -2504,6 +2541,7 @@ videoEditor_init(
(M4OSA_NULL == pContext->mAudioSettings),
"not initialized");
pContext->mAudioSettings->pFile = M4OSA_NULL;
+ pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL;
pContext->mAudioSettings->bRemoveOriginal = 0;
pContext->mAudioSettings->uiNbChannels = 0;
pContext->mAudioSettings->uiSamplingFrequency = 0;
@@ -2995,6 +3033,15 @@ videoEditor_release(
pContext->mPreviewController = M4OSA_NULL;
}
+ if (pContext->mAudioSettings->pFile != NULL) {
+ M4OSA_free((M4OSA_MemAddr32)pContext->mAudioSettings->pFile);
+ pContext->mAudioSettings->pFile = M4OSA_NULL;
+ }
+ if (pContext->mAudioSettings->pPCMFilePath != NULL) {
+ M4OSA_free((M4OSA_MemAddr32)pContext->mAudioSettings->pPCMFilePath);
+ pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL;
+ }
+
// Free the context.
if(pContext->mAudioSettings != M4OSA_NULL)
{
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 26397bbd81c5..8e39a63fe372 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -1414,13 +1414,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
LinkProperties p = nt.getLinkProperties();
if (p == null) return;
String interfaceName = p.getInterfaceName();
- InetAddress defaultGatewayAddr = p.getGateway();
+ if (TextUtils.isEmpty(interfaceName)) return;
+ for (InetAddress gateway : p.getGateways()) {
- if ((interfaceName != null) && (defaultGatewayAddr != null )) {
- if (!NetworkUtils.addDefaultRoute(interfaceName, defaultGatewayAddr) && DBG) {
+ if (!NetworkUtils.addDefaultRoute(interfaceName, gateway) && DBG) {
NetworkInfo networkInfo = nt.getNetworkInfo();
log("addDefaultRoute for " + networkInfo.getTypeName() +
- " (" + interfaceName + "), GatewayAddr=" + defaultGatewayAddr);
+ " (" + interfaceName + "), GatewayAddr=" + gateway.getHostAddress());
}
}
}
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 55d18443ad82..d4117159477b 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -445,7 +445,10 @@ class WifiConfigStore {
if (iter.hasNext()) {
LinkAddress linkAddress = iter.next();
dhcpInfoInternal.ipAddress = linkAddress.getAddress().getHostAddress();
- dhcpInfoInternal.gateway = linkProperties.getGateway().getHostAddress();
+ Iterator<InetAddress>gateways = linkProperties.getGateways().iterator();
+ if (gateways.hasNext()) {
+ dhcpInfoInternal.gateway = gateways.next().getHostAddress();
+ }
dhcpInfoInternal.prefixLength = linkAddress.getNetworkPrefixLength();
Iterator<InetAddress> dnsIterator = linkProperties.getDnses().iterator();
dhcpInfoInternal.dns1 = dnsIterator.next().getHostAddress();
@@ -582,8 +585,7 @@ class WifiConfigStore {
out.writeUTF(linkAddr.getAddress().getHostAddress());
out.writeInt(linkAddr.getNetworkPrefixLength());
}
- InetAddress gateway = linkProperties.getGateway();
- if (gateway != null) {
+ for (InetAddress gateway : linkProperties.getGateways()) {
out.writeUTF(GATEWAY_KEY);
out.writeUTF(gateway.getHostAddress());
}
@@ -688,7 +690,7 @@ class WifiConfigStore {
in.readUTF()), in.readInt());
linkProperties.addLinkAddress(linkAddr);
} else if (key.equals(GATEWAY_KEY)) {
- linkProperties.setGateway(InetAddress.getByName(in.readUTF()));
+ linkProperties.addGateway(InetAddress.getByName(in.readUTF()));
} else if (key.equals(DNS_KEY)) {
linkProperties.addDns(InetAddress.getByName(in.readUTF()));
} else if (key.equals(PROXY_SETTINGS_KEY)) {
@@ -999,15 +1001,17 @@ class WifiConfigStore {
.getLinkAddresses();
Collection<InetAddress> currentDnses = currentConfig.linkProperties.getDnses();
Collection<InetAddress> newDnses = newConfig.linkProperties.getDnses();
- InetAddress currentGateway = currentConfig.linkProperties.getGateway();
- InetAddress newGateway = newConfig.linkProperties.getGateway();
-
- boolean linkAddressesDiffer = !currentLinkAddresses.containsAll(newLinkAddresses) ||
- (currentLinkAddresses.size() != newLinkAddresses.size());
- boolean dnsesDiffer = !currentDnses.containsAll(newDnses) ||
- (currentDnses.size() != newDnses.size());
- boolean gatewaysDiffer = (currentGateway == null) ||
- !currentGateway.equals(newGateway);
+ Collection<InetAddress> currentGateways =
+ currentConfig.linkProperties.getGateways();
+ Collection<InetAddress> newGateways = newConfig.linkProperties.getGateways();
+
+ boolean linkAddressesDiffer =
+ (currentLinkAddresses.size() != newLinkAddresses.size()) ||
+ !currentLinkAddresses.containsAll(newLinkAddresses);
+ boolean dnsesDiffer = (currentDnses.size() != newDnses.size()) ||
+ !currentDnses.containsAll(newDnses);
+ boolean gatewaysDiffer = (currentGateways.size() != newGateways.size()) ||
+ !currentGateways.containsAll(newGateways);
if ((currentConfig.ipAssignment != newConfig.ipAssignment) ||
linkAddressesDiffer ||
@@ -1087,7 +1091,9 @@ class WifiConfigStore {
for (LinkAddress linkAddr : config.linkProperties.getLinkAddresses()) {
linkProperties.addLinkAddress(linkAddr);
}
- linkProperties.setGateway(config.linkProperties.getGateway());
+ for (InetAddress gateway : config.linkProperties.getGateways()) {
+ linkProperties.addGateway(gateway);
+ }
for (InetAddress dns : config.linkProperties.getDnses()) {
linkProperties.addDns(dns);
}