Merge change 24020 into eclair

* changes:
  Wallpapers: new transitions, hiding when not visible, other cleanup.
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index 1edcb0a..6d870da 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -19,6 +19,8 @@
 import android.accounts.Account;
 import android.os.Bundle;
 import android.os.Process;
+import android.os.NetStat;
+import android.util.EventLog;
 
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -45,6 +47,7 @@
 
     /** Kernel event log tag.  Also listed in data/etc/event-log-tags. */
     public static final int LOG_SYNC_DETAILS = 2743;
+    private static final String TAG = "Sync";
     private final boolean mAutoInitialize;
 
     /**
@@ -127,6 +130,8 @@
         private final String mAuthority;
         private final Account mAccount;
         private final Bundle mExtras;
+        private long mInitialTxBytes;
+        private long mInitialRxBytes;
 
         private SyncThread(String name, SyncContext syncContext, String authority,
                 Account account, Bundle extras) {
@@ -145,6 +150,9 @@
             }
 
             SyncResult syncResult = new SyncResult();
+            int uid = Process.myUid();
+            mInitialTxBytes = NetStat.getUidTxBytes(uid);
+            mInitialRxBytes = NetStat.getUidRxBytes(uid);
             ContentProviderClient provider = null;
             try {
                 provider = mContext.getContentResolver().acquireContentProviderClient(mAuthority);
@@ -162,6 +170,8 @@
                 if (!isCanceled()) {
                     mSyncContext.onFinished(syncResult);
                 }
+                logSyncDetails(NetStat.getUidTxBytes(uid) - mInitialTxBytes,
+                        NetStat.getUidRxBytes(uid) - mInitialRxBytes, syncResult);
                 // synchronize so that the assignment will be seen by other threads
                 // that also synchronize accesses to mSyncThread
                 synchronized (mSyncThreadLock) {
@@ -196,4 +206,18 @@
      */
     public abstract void performSync(Account account, Bundle extras,
             String authority, ContentProviderClient provider, SyncResult syncResult);
+
+    /**
+     * Logs details on the sync.
+     * Normally this will be overridden by a subclass that will provide
+     * provider-specific details.
+     *
+     * @param bytesSent number of bytes the sync sent over the network
+     * @param bytesReceived number of bytes the sync received over the network
+     * @param result The SyncResult object holding info on the sync
+     */
+    protected void logSyncDetails(long bytesSent, long bytesReceived, SyncResult result) {
+        EventLog.writeEvent(SyncAdapter.LOG_SYNC_DETAILS, TAG, bytesSent, bytesReceived, "");
+    }
+
 }
\ No newline at end of file
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 3ff13ae..df3d241 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -54,14 +54,14 @@
 /**
  * Singleton that tracks the sync data and overall sync
  * history on the device.
- * 
+ *
  * @hide
  */
 public class SyncStorageEngine extends Handler {
     private static final String TAG = "SyncManager";
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_FILE = false;
-    
+
     // @VisibleForTesting
     static final long MILLIS_IN_4WEEKS = 1000L * 60 * 60 * 24 * 7 * 4;
 
@@ -104,24 +104,24 @@
     public static final String MESG_CANCELED = "canceled";
 
     public static final int MAX_HISTORY = 15;
-    
+
     private static final int MSG_WRITE_STATUS = 1;
     private static final long WRITE_STATUS_DELAY = 1000*60*10; // 10 minutes
-    
+
     private static final int MSG_WRITE_STATISTICS = 2;
     private static final long WRITE_STATISTICS_DELAY = 1000*60*30; // 1/2 hour
 
     private static final boolean SYNC_ENABLED_DEFAULT = false;
-    
+
     public static class PendingOperation {
         final Account account;
         final int syncSource;
         final String authority;
         final Bundle extras;        // note: read-only.
-        
+
         int authorityId;
         byte[] flatExtras;
-        
+
         PendingOperation(Account account, int source,
                 String authority, Bundle extras) {
             this.account = account;
@@ -139,17 +139,17 @@
             this.authorityId = other.authorityId;
         }
     }
-    
+
     static class AccountInfo {
         final Account account;
         final HashMap<String, AuthorityInfo> authorities =
                 new HashMap<String, AuthorityInfo>();
-        
+
         AccountInfo(Account account) {
             this.account = account;
         }
     }
-    
+
     public static class AuthorityInfo {
         final Account account;
         final String authority;
@@ -165,7 +165,7 @@
             syncable = -1; // default to "unknown"
         }
     }
-    
+
     public static class SyncHistoryItem {
         int authorityId;
         int historyId;
@@ -177,69 +177,69 @@
         long downstreamActivity;
         String mesg;
     }
-    
+
     public static class DayStats {
         public final int day;
         public int successCount;
         public long successTime;
         public int failureCount;
         public long failureTime;
-        
+
         public DayStats(int day) {
             this.day = day;
         }
     }
-    
+
     // Primary list of all syncable authorities.  Also our global lock.
     private final SparseArray<AuthorityInfo> mAuthorities =
             new SparseArray<AuthorityInfo>();
-    
+
     private final HashMap<Account, AccountInfo> mAccounts =
         new HashMap<Account, AccountInfo>();
 
     private final ArrayList<PendingOperation> mPendingOperations =
             new ArrayList<PendingOperation>();
-    
+
     private ActiveSyncInfo mActiveSync;
-    
+
     private final SparseArray<SyncStatusInfo> mSyncStatus =
             new SparseArray<SyncStatusInfo>();
-    
+
     private final ArrayList<SyncHistoryItem> mSyncHistory =
             new ArrayList<SyncHistoryItem>();
-    
+
     private final RemoteCallbackList<ISyncStatusObserver> mChangeListeners
             = new RemoteCallbackList<ISyncStatusObserver>();
-    
+
     // We keep 4 weeks of stats.
     private final DayStats[] mDayStats = new DayStats[7*4];
     private final Calendar mCal;
     private int mYear;
     private int mYearInDays;
-    
+
     private final Context mContext;
     private static volatile SyncStorageEngine sSyncStorageEngine = null;
-    
+
     /**
      * This file contains the core engine state: all accounts and the
      * settings for them.  It must never be lost, and should be changed
      * infrequently, so it is stored as an XML file.
      */
     private final AtomicFile mAccountInfoFile;
-    
+
     /**
      * This file contains the current sync status.  We would like to retain
      * it across boots, but its loss is not the end of the world, so we store
      * this information as binary data.
      */
     private final AtomicFile mStatusFile;
-    
+
     /**
      * This file contains sync statistics.  This is purely debugging information
      * so is written infrequently and can be thrown away at any time.
      */
     private final AtomicFile mStatisticsFile;
-    
+
     /**
      * This file contains the pending sync operations.  It is a binary file,
      * which must be updated every time an operation is added or removed,
@@ -248,16 +248,16 @@
     private final AtomicFile mPendingFile;
     private static final int PENDING_FINISH_TO_WRITE = 4;
     private int mNumPendingFinished = 0;
-    
+
     private int mNextHistoryId = 0;
     private boolean mMasterSyncAutomatically = true;
-    
+
     private SyncStorageEngine(Context context) {
         mContext = context;
         sSyncStorageEngine = this;
-        
+
         mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
-        
+
         File dataDir = Environment.getDataDirectory();
         File systemDir = new File(dataDir, "system");
         File syncDir = new File(systemDir, "sync");
@@ -265,7 +265,7 @@
         mStatusFile = new AtomicFile(new File(syncDir, "status.bin"));
         mPendingFile = new AtomicFile(new File(syncDir, "pending.bin"));
         mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"));
-        
+
         readAccountInfoLocked();
         readStatusLocked();
         readPendingOperationsLocked();
@@ -302,19 +302,19 @@
             }
         }
     }
-    
+
     public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
         synchronized (mAuthorities) {
             mChangeListeners.register(callback, mask);
         }
     }
-    
+
     public void removeStatusChangeListener(ISyncStatusObserver callback) {
         synchronized (mAuthorities) {
             mChangeListeners.unregister(callback);
         }
     }
-    
+
     private void reportChange(int which) {
         ArrayList<ISyncStatusObserver> reports = null;
         synchronized (mAuthorities) {
@@ -332,9 +332,9 @@
             }
             mChangeListeners.finishBroadcast();
         }
-        
+
         if (DEBUG) Log.v(TAG, "reportChange " + which + " to: " + reports);
-        
+
         if (reports != null) {
             int i = reports.size();
             while (i > 0) {
@@ -369,7 +369,7 @@
             int i = mAuthorities.size();
             while (i > 0) {
                 i--;
-                AuthorityInfo authority = mAuthorities.get(i);
+                AuthorityInfo authority = mAuthorities.valueAt(i);
                 if (authority.authority.equals(providerName)
                         && authority.enabled) {
                     return true;
@@ -408,7 +408,7 @@
             int i = mAuthorities.size();
             while (i > 0) {
                 i--;
-                AuthorityInfo authority = mAuthorities.get(i);
+                AuthorityInfo authority = mAuthorities.valueAt(i);
                 if (authority.authority.equals(providerName)) {
                     return authority.syncable;
                 }
@@ -457,19 +457,19 @@
             return mMasterSyncAutomatically;
         }
     }
-    
+
     public AuthorityInfo getAuthority(Account account, String authority) {
         synchronized (mAuthorities) {
             return getAuthorityLocked(account, authority, null);
         }
     }
-    
+
     public AuthorityInfo getAuthority(int authorityId) {
         synchronized (mAuthorities) {
             return mAuthorities.get(authorityId);
         }
     }
-    
+
     /**
      * Returns true if there is currently a sync operation for the given
      * account or authority in the pending list, or actively being processed.
@@ -486,7 +486,7 @@
                     return true;
                 }
             }
-            
+
             if (mActiveSync != null) {
                 AuthorityInfo ainfo = getAuthority(mActiveSync.authorityId);
                 if (ainfo != null && ainfo.account.equals(account)
@@ -495,17 +495,17 @@
                 }
             }
         }
-        
+
         return false;
     }
-    
+
     public PendingOperation insertIntoPending(PendingOperation op) {
         synchronized (mAuthorities) {
             if (DEBUG) Log.v(TAG, "insertIntoPending: account=" + op.account
                     + " auth=" + op.authority
                     + " src=" + op.syncSource
                     + " extras=" + op.extras);
-            
+
             AuthorityInfo authority = getOrCreateAuthorityLocked(op.account,
                     op.authority,
                     -1 /* desired identifier */,
@@ -513,16 +513,16 @@
             if (authority == null) {
                 return null;
             }
-            
+
             op = new PendingOperation(op);
             op.authorityId = authority.ident;
             mPendingOperations.add(op);
             appendPendingOperationLocked(op);
-            
+
             SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
             status.pending = true;
         }
-        
+
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
         return op;
     }
@@ -542,7 +542,7 @@
                 } else {
                     mNumPendingFinished++;
                 }
-                
+
                 AuthorityInfo authority = getAuthorityLocked(op.account, op.authority,
                         "deleteFromPending");
                 if (authority != null) {
@@ -557,18 +557,18 @@
                             break;
                         }
                     }
-                    
+
                     if (!morePending) {
                         if (DEBUG) Log.v(TAG, "no more pending!");
                         SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
                         status.pending = false;
                     }
                 }
-                
+
                 res = true;
             }
         }
-        
+
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
         return res;
     }
@@ -581,7 +581,7 @@
             mPendingOperations.clear();
             final int N = mSyncStatus.size();
             for (int i=0; i<N; i++) {
-                mSyncStatus.get(i).pending = false;
+                mSyncStatus.valueAt(i).pending = false;
             }
             writePendingOperationsLocked();
         }
@@ -599,7 +599,7 @@
             return new ArrayList<PendingOperation>(mPendingOperations);
         }
     }
-    
+
     /**
      * Return the number of currently pending operations.
      */
@@ -608,7 +608,7 @@
             return mPendingOperations.size();
         }
     }
-    
+
     /**
      * Called when the set of account has changed, given the new array of
      * active accounts.
@@ -629,7 +629,7 @@
                     accIt.remove();
                 }
             }
-            
+
             // Clean out all data structures.
             int i = removing.size();
             if (i > 0) {
@@ -691,7 +691,7 @@
                 mActiveSync = null;
             }
         }
-        
+
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
     }
 
@@ -701,7 +701,7 @@
     public void reportActiveChange() {
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
     }
-    
+
     /**
      * Note that sync has started for the given account and authority.
      */
@@ -730,7 +730,7 @@
             id = item.historyId;
             if (DEBUG) Log.v(TAG, "returning historyId " + id);
         }
-        
+
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
         return id;
     }
@@ -749,20 +749,20 @@
                 }
                 item = null;
             }
-            
+
             if (item == null) {
                 Log.w(TAG, "stopSyncEvent: no history for id " + historyId);
                 return;
             }
-            
+
             item.elapsedTime = elapsedTime;
             item.event = EVENT_STOP;
             item.mesg = resultMessage;
             item.downstreamActivity = downstreamActivity;
             item.upstreamActivity = upstreamActivity;
-            
+
             SyncStatusInfo status = getOrCreateSyncStatusLocked(item.authorityId);
-            
+
             status.numSyncs++;
             status.totalElapsedTime += elapsedTime;
             switch (item.source) {
@@ -779,7 +779,7 @@
                     status.numSourceServer++;
                     break;
             }
-            
+
             boolean writeStatisticsNow = false;
             int day = getCurrentDayLocked();
             if (mDayStats[0] == null) {
@@ -791,7 +791,7 @@
             } else if (mDayStats[0] == null) {
             }
             final DayStats ds = mDayStats[0];
-            
+
             final long lastSyncTime = (item.eventTime + elapsedTime);
             boolean writeStatusNow = false;
             if (MESG_SUCCESS.equals(resultMessage)) {
@@ -820,7 +820,7 @@
                 ds.failureCount++;
                 ds.failureTime += elapsedTime;
             }
-            
+
             if (writeStatusNow) {
                 writeStatusLocked();
             } else if (!hasMessages(MSG_WRITE_STATUS)) {
@@ -832,9 +832,9 @@
             } else if (!hasMessages(MSG_WRITE_STATISTICS)) {
                 sendMessageDelayed(obtainMessage(MSG_WRITE_STATISTICS),
                         WRITE_STATISTICS_DELAY);
-            }            
+            }
         }
-        
+
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
     }
 
@@ -848,7 +848,7 @@
             return mActiveSync;
         }
     }
-    
+
     /**
      * Return an array of the current sync status for all authorities.  Note
      * that the objects inside the array are the real, live status objects,
@@ -864,7 +864,7 @@
             return ops;
         }
     }
-    
+
     /**
      * Returns the status that matches the authority. If there are multiples accounts for
      * the authority, the one with the latest "lastSuccessTime" status is returned.
@@ -876,7 +876,7 @@
             SyncStatusInfo best = null;
             final int N = mSyncStatus.size();
             for (int i=0; i<N; i++) {
-                SyncStatusInfo cur = mSyncStatus.get(i);
+                SyncStatusInfo cur = mSyncStatus.valueAt(i);
                 AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
                 if (ainfo != null && ainfo.authority.equals(authority)) {
                     if (best == null) {
@@ -889,7 +889,7 @@
             return best;
         }
     }
-    
+
     /**
      * Return true if the pending status is true of any matching authorities.
      */
@@ -897,7 +897,7 @@
         synchronized (mAuthorities) {
             final int N = mSyncStatus.size();
             for (int i=0; i<N; i++) {
-                SyncStatusInfo cur = mSyncStatus.get(i);
+                SyncStatusInfo cur = mSyncStatus.valueAt(i);
                 AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
                 if (ainfo == null) {
                     continue;
@@ -928,7 +928,7 @@
             return items;
         }
     }
-    
+
     /**
      * Return an array of the current per-day statistics.  Note
      * that the objects inside the array are the real, live status objects,
@@ -941,7 +941,7 @@
             return ds;
         }
     }
-    
+
     /**
      * If sync is failing for any of the provider/accounts then determine the time at which it
      * started failing and return the earliest time over all the provider/accounts. If none are
@@ -952,7 +952,7 @@
             if (!mMasterSyncAutomatically) {
                 return 0;
             }
-            
+
             long oldest = 0;
             int i = mSyncStatus.size();
             while (i > 0) {
@@ -965,11 +965,11 @@
                     }
                 }
             }
-            
+
             return oldest;
         }
     }
-    
+
     private int getCurrentDayLocked() {
         mCal.setTimeInMillis(System.currentTimeMillis());
         final int dayOfYear = mCal.get(Calendar.DAY_OF_YEAR);
@@ -981,10 +981,10 @@
         }
         return dayOfYear + mYearInDays;
     }
-    
+
     /**
      * Retrieve an authority, returning null if one does not exist.
-     * 
+     *
      * @param accountName The name of the account for the authority.
      * @param authorityName The name of the authority itself.
      * @param tag If non-null, this will be used in a log message if the
@@ -1010,10 +1010,10 @@
             }
             return null;
         }
-        
+
         return authority;
     }
-    
+
     private AuthorityInfo getOrCreateAuthorityLocked(Account accountName,
             String authorityName, int ident, boolean doWrite) {
         AccountInfo account = mAccounts.get(accountName);
@@ -1043,10 +1043,10 @@
                 writeAccountInfoLocked();
             }
         }
-        
+
         return authority;
     }
-    
+
     private SyncStatusInfo getOrCreateSyncStatusLocked(int authorityId) {
         SyncStatusInfo status = mSyncStatus.get(authorityId);
         if (status == null) {
@@ -1055,22 +1055,22 @@
         }
         return status;
     }
-    
+
     public void writeAllState() {
         synchronized (mAuthorities) {
             // Account info is always written so no need to do it here.
-            
+
             if (mNumPendingFinished > 0) {
                 // Only write these if they are out of date.
                 writePendingOperationsLocked();
             }
-            
+
             // Just always write these...  they are likely out of date.
             writeStatusLocked();
             writeStatisticsLocked();
         }
     }
-    
+
     /**
      * Read all account information back in to the initial engine state.
      */
@@ -1165,29 +1165,29 @@
             }
         }
     }
-    
+
     /**
      * Write all account information to the account file.
      */
     private void writeAccountInfoLocked() {
         if (DEBUG_FILE) Log.v(TAG, "Writing new " + mAccountInfoFile.getBaseFile());
         FileOutputStream fos = null;
-        
+
         try {
             fos = mAccountInfoFile.startWrite();
             XmlSerializer out = new FastXmlSerializer();
             out.setOutput(fos, "utf-8");
             out.startDocument(null, true);
             out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-            
+
             out.startTag(null, "accounts");
             if (!mMasterSyncAutomatically) {
                 out.attribute(null, "listen-for-tickles", "false");
             }
-            
+
             final int N = mAuthorities.size();
             for (int i=0; i<N; i++) {
-                AuthorityInfo authority = mAuthorities.get(i);
+                AuthorityInfo authority = mAuthorities.valueAt(i);
                 out.startTag(null, "authority");
                 out.attribute(null, "id", Integer.toString(authority.ident));
                 out.attribute(null, "account", authority.account.name);
@@ -1203,11 +1203,11 @@
                 }
                 out.endTag(null, "authority");
             }
-            
+
             out.endTag(null, "accounts");
-            
+
             out.endDocument();
-            
+
             mAccountInfoFile.finishWrite(fos);
         } catch (java.io.IOException e1) {
             Log.w(TAG, "Error writing accounts", e1);
@@ -1216,15 +1216,15 @@
             }
         }
     }
-    
+
     static int getIntColumn(Cursor c, String name) {
         return c.getInt(c.getColumnIndex(name));
     }
-    
+
     static long getLongColumn(Cursor c, String name) {
         return c.getLong(c.getColumnIndex(name));
     }
-    
+
     /**
      * Load sync engine state from the old syncmanager database, and then
      * erase it.  Note that we don't deal with pending operations, active
@@ -1243,10 +1243,10 @@
                     SQLiteDatabase.OPEN_READONLY);
         } catch (SQLiteException e) {
         }
-        
+
         if (db != null) {
             final boolean hasType = db.getVersion() >= 11;
-            
+
             // Copy in all of the status information, as well as accounts.
             if (DEBUG_FILE) Log.v(TAG, "Reading legacy sync accounts db");
             SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
@@ -1290,7 +1290,7 @@
                     SyncStatusInfo st = null;
                     while (i > 0) {
                         i--;
-                        st = mSyncStatus.get(i);
+                        st = mSyncStatus.valueAt(i);
                         if (st.authorityId == authority.ident) {
                             found = true;
                             break;
@@ -1314,9 +1314,9 @@
                     st.pending = getIntColumn(c, "pending") != 0;
                 }
             }
-            
+
             c.close();
-            
+
             // Retrieve the settings.
             qb = new SQLiteQueryBuilder();
             qb.setTables("settings");
@@ -1333,7 +1333,7 @@
                     int i = mAuthorities.size();
                     while (i > 0) {
                         i--;
-                        AuthorityInfo authority = mAuthorities.get(i);
+                        AuthorityInfo authority = mAuthorities.valueAt(i);
                         if (authority.authority.equals(provider)) {
                             authority.enabled = value == null || Boolean.parseBoolean(value);
                             authority.syncable = 1;
@@ -1341,20 +1341,20 @@
                     }
                 }
             }
-            
+
             c.close();
-            
+
             db.close();
-            
+
             writeAccountInfoLocked();
             writeStatusLocked();
             (new File(path)).delete();
         }
     }
-    
+
     public static final int STATUS_FILE_END = 0;
     public static final int STATUS_FILE_ITEM = 100;
-    
+
     /**
      * Read all sync status back in to the initial engine state.
      */
@@ -1385,17 +1385,17 @@
             Log.i(TAG, "No initial status");
         }
     }
-    
+
     /**
      * Write all sync status to the sync status file.
      */
     private void writeStatusLocked() {
         if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatusFile.getBaseFile());
-        
+
         // The file is being written, so we don't need to have a scheduled
         // write until the next change.
         removeMessages(MSG_WRITE_STATUS);
-        
+
         FileOutputStream fos = null;
         try {
             fos = mStatusFile.startWrite();
@@ -1409,7 +1409,7 @@
             out.writeInt(STATUS_FILE_END);
             fos.write(out.marshall());
             out.recycle();
-            
+
             mStatusFile.finishWrite(fos);
         } catch (java.io.IOException e1) {
             Log.w(TAG, "Error writing status", e1);
@@ -1418,9 +1418,9 @@
             }
         }
     }
-    
+
     public static final int PENDING_OPERATION_VERSION = 1;
-    
+
     /**
      * Read all pending operations back in to the initial engine state.
      */
@@ -1464,7 +1464,7 @@
             Log.i(TAG, "No initial pending operations");
         }
     }
-    
+
     private void writePendingOperationLocked(PendingOperation op, Parcel out) {
         out.writeInt(PENDING_OPERATION_VERSION);
         out.writeInt(op.authorityId);
@@ -1474,7 +1474,7 @@
         }
         out.writeByteArray(op.flatExtras);
     }
-    
+
     /**
      * Write all currently pending ops to the pending ops file.
      */
@@ -1487,10 +1487,10 @@
                 mPendingFile.truncate();
                 return;
             }
-            
+
             if (DEBUG_FILE) Log.v(TAG, "Writing new " + mPendingFile.getBaseFile());
             fos = mPendingFile.startWrite();
-        
+
             Parcel out = Parcel.obtain();
             for (int i=0; i<N; i++) {
                 PendingOperation op = mPendingOperations.get(i);
@@ -1498,7 +1498,7 @@
             }
             fos.write(out.marshall());
             out.recycle();
-            
+
             mPendingFile.finishWrite(fos);
         } catch (java.io.IOException e1) {
             Log.w(TAG, "Error writing pending operations", e1);
@@ -1507,7 +1507,7 @@
             }
         }
     }
-    
+
     /**
      * Append the given operation to the pending ops file; if unable to,
      * write all pending ops.
@@ -1522,7 +1522,7 @@
             writePendingOperationsLocked();
             return;
         }
-        
+
         try {
             Parcel out = Parcel.obtain();
             writePendingOperationLocked(op, out);
@@ -1537,7 +1537,7 @@
             }
         }
     }
-    
+
     static private byte[] flattenBundle(Bundle bundle) {
         byte[] flatData = null;
         Parcel parcel = Parcel.obtain();
@@ -1549,7 +1549,7 @@
         }
         return flatData;
     }
-    
+
     static private Bundle unflattenBundle(byte[] flatData) {
         Bundle bundle;
         Parcel parcel = Parcel.obtain();
@@ -1566,11 +1566,11 @@
         }
         return bundle;
     }
-    
+
     public static final int STATISTICS_FILE_END = 0;
     public static final int STATISTICS_FILE_ITEM_OLD = 100;
     public static final int STATISTICS_FILE_ITEM = 101;
-    
+
     /**
      * Read all sync statistics back in to the initial engine state.
      */
@@ -1608,17 +1608,17 @@
             Log.i(TAG, "No initial statistics");
         }
     }
-    
+
     /**
      * Write all sync statistics to the sync status file.
      */
     private void writeStatisticsLocked() {
         if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatisticsFile.getBaseFile());
-        
+
         // The file is being written, so we don't need to have a scheduled
         // write until the next change.
         removeMessages(MSG_WRITE_STATISTICS);
-        
+
         FileOutputStream fos = null;
         try {
             fos = mStatisticsFile.startWrite();
@@ -1639,7 +1639,7 @@
             out.writeInt(STATISTICS_FILE_END);
             fos.write(out.marshall());
             out.recycle();
-            
+
             mStatisticsFile.finishWrite(fos);
         } catch (java.io.IOException e1) {
             Log.w(TAG, "Error writing stats", e1);
diff --git a/core/java/android/webkit/ViewManager.java b/core/java/android/webkit/ViewManager.java
index 63f4033..6a838c3 100644
--- a/core/java/android/webkit/ViewManager.java
+++ b/core/java/android/webkit/ViewManager.java
@@ -50,7 +50,7 @@
             }
             setBounds(x, y, width, height);
             final AbsoluteLayout.LayoutParams lp =
-                    new AbsoluteLayout.LayoutParams(ctvX(width), ctvX(height),
+                    new AbsoluteLayout.LayoutParams(ctvD(width), ctvD(height),
                             ctvX(x), ctvY(y));
             mWebView.mPrivateHandler.post(new Runnable() {
                 public void run() {
@@ -98,9 +98,17 @@
     }
 
     /**
+     * Shorthand for calling mWebView.contentToViewDimension.  Used when
+     * obtaining a view dimension from a content dimension, whether it be in x
+     * or y.
+     */
+    private int ctvD(int val) {
+        return mWebView.contentToViewDimension(val);
+    }
+
+    /**
      * Shorthand for calling mWebView.contentToViewX.  Used when obtaining a
-     * view x coordinate from a content x coordinate, or when getting a
-     * view dimension from a content dimension, whether it be in x or y.
+     * view x coordinate from a content x coordinate.
      */
     private int ctvX(int val) {
         return mWebView.contentToViewX(val);
@@ -119,8 +127,8 @@
             View view = v.mView;
             AbsoluteLayout.LayoutParams lp =
                     (AbsoluteLayout.LayoutParams) view.getLayoutParams();
-            lp.width = ctvX(v.width);
-            lp.height = ctvX(v.height);
+            lp.width = ctvD(v.width);
+            lp.height = ctvD(v.height);
             lp.x = ctvX(v.x);
             lp.y = ctvY(v.y);
             view.setLayoutParams(lp);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 8d21b33..db6966a 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -58,6 +58,7 @@
 import android.view.ViewParent;
 import android.view.ViewTreeObserver;
 import android.view.animation.AlphaAnimation;
+import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.webkit.WebTextView.AutoCompleteAdapter;
 import android.webkit.WebViewCore.EventHub;
@@ -1776,13 +1777,15 @@
      * the WebView normally without translating to account for the title bar.
      * @hide
      */
-    public void addTitleBar(View v) {
-        if (null == v) {
+    public void setEmbeddedTitleBar(View v) {
+        if (mTitleBar == v) return;
+        if (mTitleBar != null) {
             removeView(mTitleBar);
-        } else {
+        }
+        if (null != v) {
             addView(v, new AbsoluteLayout.LayoutParams(
                     ViewGroup.LayoutParams.FILL_PARENT,
-                    ViewGroup.LayoutParams.WRAP_CONTENT, mScrollX, 0));
+                    ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0));
         }
         mTitleBar = v;
     }
@@ -2731,6 +2734,15 @@
         }
     }
 
+    /**
+     * Need to adjust the WebTextView after a change in zoom, since mActualScale
+     * has changed.  This is especially important for password fields, which are
+     * drawn by the WebTextView, since it conveys more information than what
+     * webkit draws.  Thus we need to reposition it to show in the correct
+     * place.
+     */
+    private boolean mNeedToAdjustWebTextView;
+
     private void drawCoreAndCursorRing(Canvas canvas, int color,
         boolean drawCursorRing) {
         if (mDrawHistory) {
@@ -2754,6 +2766,20 @@
                 zoomScale = mZoomScale;
                 // set mZoomScale to be 0 as we have done animation
                 mZoomScale = 0;
+                if (mNeedToAdjustWebTextView) {
+                    mNeedToAdjustWebTextView = false;
+                    mWebTextView.setTextSize(contentToViewDimension(
+                            nativeFocusCandidateTextSize()));
+                    Rect bounds = nativeFocusCandidateNodeBounds();
+                    Rect vBox = contentToView(bounds);
+                    mWebTextView.setRect(vBox.left, vBox.top, vBox.width(),
+                            vBox.height());
+                    // If it is a password field, start drawing the
+                    // WebTextView once again.
+                    if (nativeFocusCandidateIsPassword()) {
+                        mWebTextView.setInPassword(true);
+                    }
+                }
             }
             float scale = zoomScale * mInvInitialZoomScale;
             int tx = Math.round(scale * (mInitialScrollX + mZoomCenterX)
@@ -2766,6 +2792,17 @@
                     * zoomScale)) + mScrollY;
             canvas.translate(tx, ty);
             canvas.scale(zoomScale, zoomScale);
+            if (inEditingMode() && !mNeedToAdjustWebTextView
+                    && mZoomScale != 0) {
+                // The WebTextView is up.  Keep track of this so we can adjust
+                // its size and placement when we finish zooming
+                mNeedToAdjustWebTextView = true;
+                // If it is in password mode, turn it off so it does not draw
+                // misplaced.
+                if (nativeFocusCandidateIsPassword()) {
+                    mWebTextView.setInPassword(false);
+                }
+            }
         } else {
             canvas.scale(mActualScale, mActualScale);
         }
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index e6cb395..7749ad34 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -209,35 +209,24 @@
     static public Allocation createSized(RenderScript rs, Element e, int count)
         throws IllegalArgumentException {
 
-        int id;
-        if(e.mIsPredefined) {
-            id = rs.nAllocationCreatePredefSized(e.mPredefinedID, count);
-        } else {
-            id = rs.nAllocationCreateSized(e.mID, count);
-            if(id == 0) {
-                throw new IllegalStateException("Bad element.");
-            }
+        int id = rs.nAllocationCreateSized(e.mID, count);
+        if(id == 0) {
+            throw new IllegalStateException("Bad element.");
         }
         return new Allocation(id, rs, null);
     }
 
     static public Allocation createFromBitmap(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips)
         throws IllegalArgumentException {
-        if(!dstFmt.mIsPredefined) {
-            throw new IllegalStateException("Attempting to allocate a bitmap with a non-static element.");
-        }
 
-        int id = rs.nAllocationCreateFromBitmap(dstFmt.mPredefinedID, genMips, b);
+        int id = rs.nAllocationCreateFromBitmap(dstFmt.mID, genMips, b);
         return new Allocation(id, rs, null);
     }
 
     static public Allocation createFromBitmapBoxed(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips)
         throws IllegalArgumentException {
-        if(!dstFmt.mIsPredefined) {
-            throw new IllegalStateException("Attempting to allocate a bitmap with a non-static element.");
-        }
 
-        int id = rs.nAllocationCreateFromBitmapBoxed(dstFmt.mPredefinedID, genMips, b);
+        int id = rs.nAllocationCreateFromBitmapBoxed(dstFmt.mID, genMips, b);
         return new Allocation(id, rs, null);
     }
 
@@ -250,10 +239,10 @@
             is = res.openRawResource(id, value);
 
             int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
-            int allocationId = rs.nAllocationCreateFromAssetStream(dstFmt.mPredefinedID, genMips,
+            int allocationId = rs.nAllocationCreateFromAssetStream(dstFmt.mID, genMips,
                     asset);
 
-            return new Allocation(allocationId, rs, null);            
+            return new Allocation(allocationId, rs, null);
         } catch (Exception e) {
             // Ignore
         } finally {
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 0b7e667..04c36fd 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -23,62 +23,171 @@
  *
  **/
 public class Element extends BaseObj {
-    final int mPredefinedID;
-    final boolean mIsPredefined;
-    final int mSize;
+    int mSize;
+    Entry[] mEntries;
 
-    public static final Element USER_U8 = new Element(0, 1);
-    public static final Element USER_I8 = new Element(1, 1);
-    public static final Element USER_U16 = new Element(2, 2);
-    public static final Element USER_I16 = new Element(3, 2);
-    public static final Element USER_U32 = new Element(4, 4);
-    public static final Element USER_I32 = new Element(5, 4);
-    public static final Element USER_FLOAT = new Element(6, 4);
+    static class Entry {
+        Element mElement;
+        Element.DataType mType;
+        Element.DataKind mKind;
+        boolean mIsNormalized;
+        int mBits;
+        String mName;
 
-    public static final Element A_8 = new Element(7, 1);
-    public static final Element RGB_565 = new Element(8, 2);
-    public static final Element RGB_888 = new Element(11, 2);
-    public static final Element RGBA_5551 = new Element(9, 2);
-    public static final Element RGBA_4444 = new Element(10, 2);
-    public static final Element RGBA_8888 = new Element(12, 4);
+        Entry(Element e, int bits) {
+            mElement = e;
+            int mBits = bits;
+        }
 
-    public static final Element INDEX_16 = new Element(13, 2);
-    public static final Element INDEX_32 = new Element(14, 2);
-    public static final Element XY_F32 = new Element(15, 8);
-    public static final Element XYZ_F32 = new Element(16, 12);
-    public static final Element ST_XY_F32 = new Element(17, 16);
-    public static final Element ST_XYZ_F32 = new Element(18, 20);
-    public static final Element NORM_XYZ_F32 = new Element(19, 24);
-    public static final Element NORM_ST_XYZ_F32 = new Element(20, 32);
-
-    void initPredef(RenderScript rs) {
-        mID = rs.nElementGetPredefined(mPredefinedID);
+        Entry(DataType dt, DataKind dk, boolean isNorm, int bits, String name) {
+            mType = dt;
+            mKind = dk;
+            mIsNormalized = isNorm;
+            mBits = bits;
+            mName = name;
+        }
     }
 
-    static void init(RenderScript rs) {
-        USER_U8.initPredef(rs);
-        USER_I8.initPredef(rs);
-        USER_U16.initPredef(rs);
-        USER_I16.initPredef(rs);
-        USER_U32.initPredef(rs);
-        USER_I32.initPredef(rs);
-        USER_FLOAT.initPredef(rs);
+    public static final Element USER_U8 = new Element();
+    public static final Element USER_I8 = new Element();
+    public static final Element USER_U16 = new Element();
+    public static final Element USER_I16 = new Element();
+    public static final Element USER_U32 = new Element();
+    public static final Element USER_I32 = new Element();
+    public static final Element USER_FLOAT = new Element();
 
-        A_8.initPredef(rs);
-        RGB_565.initPredef(rs);
-        RGB_888.initPredef(rs);
-        RGBA_5551.initPredef(rs);
-        RGBA_4444.initPredef(rs);
-        RGBA_8888.initPredef(rs);
+    public static final Element A_8 = new Element();
+    public static final Element RGB_565 = new Element();
+    public static final Element RGB_888 = new Element();
+    public static final Element RGBA_5551 = new Element();
+    public static final Element RGBA_4444 = new Element();
+    public static final Element RGBA_8888 = new Element();
 
-        INDEX_16.initPredef(rs);
-        INDEX_32.initPredef(rs);
-        XY_F32.initPredef(rs);
-        XYZ_F32.initPredef(rs);
-        ST_XY_F32.initPredef(rs);
-        ST_XYZ_F32.initPredef(rs);
-        NORM_XYZ_F32.initPredef(rs);
-        NORM_ST_XYZ_F32.initPredef(rs);
+    public static final Element INDEX_16 = new Element();
+    public static final Element XY_F32 = new Element();
+    public static final Element XYZ_F32 = new Element();
+    public static final Element ST_XY_F32 = new Element();
+    public static final Element ST_XYZ_F32 = new Element();
+    public static final Element NORM_XYZ_F32 = new Element();
+    public static final Element NORM_ST_XYZ_F32 = new Element();
+
+    static void initPredefined(RenderScript rs) {
+        USER_U8.mEntries = new Entry[1];
+        USER_U8.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.USER, false, 8, null);
+        USER_U8.init(rs);
+
+        USER_I8.mEntries = new Entry[1];
+        USER_I8.mEntries[0] = new Entry(DataType.SIGNED, DataKind.USER, false, 8, null);
+        USER_I8.init(rs);
+
+        USER_U16.mEntries = new Entry[1];
+        USER_U16.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.USER, false, 16, null);
+        USER_U16.init(rs);
+
+        USER_I16.mEntries = new Entry[1];
+        USER_I16.mEntries[0] = new Entry(DataType.SIGNED, DataKind.USER, false, 16, null);
+        USER_I16.init(rs);
+
+        USER_U32.mEntries = new Entry[1];
+        USER_U32.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.USER, false, 32, null);
+        USER_U32.init(rs);
+
+        USER_I32.mEntries = new Entry[1];
+        USER_I32.mEntries[0] = new Entry(DataType.SIGNED, DataKind.USER, false, 32, null);
+        USER_I32.init(rs);
+
+        USER_FLOAT.mEntries = new Entry[1];
+        USER_FLOAT.mEntries[0] = new Entry(DataType.FLOAT, DataKind.USER, false, 32, null);
+        USER_FLOAT.init(rs);
+
+        A_8.mEntries = new Entry[1];
+        A_8.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.ALPHA, true, 8, "a");
+        A_8.init(rs);
+
+        RGB_565.mEntries = new Entry[3];
+        RGB_565.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 5, "r");
+        RGB_565.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 6, "g");
+        RGB_565.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 5, "b");
+        RGB_565.init(rs);
+
+        RGB_888.mEntries = new Entry[3];
+        RGB_888.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 8, "r");
+        RGB_888.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 8, "g");
+        RGB_888.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 8, "b");
+        RGB_888.init(rs);
+
+        RGBA_5551.mEntries = new Entry[4];
+        RGBA_5551.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 5, "r");
+        RGBA_5551.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 5, "g");
+        RGBA_5551.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 5, "b");
+        RGBA_5551.mEntries[3] = new Entry(DataType.UNSIGNED, DataKind.ALPHA, true, 1, "a");
+        RGBA_5551.init(rs);
+
+        RGBA_4444.mEntries = new Entry[4];
+        RGBA_4444.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 4, "r");
+        RGBA_4444.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 4, "g");
+        RGBA_4444.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 4, "b");
+        RGBA_4444.mEntries[3] = new Entry(DataType.UNSIGNED, DataKind.ALPHA, true, 4, "a");
+        RGBA_4444.init(rs);
+
+        RGBA_8888.mEntries = new Entry[4];
+        RGBA_8888.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 8, "r");
+        RGBA_8888.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 8, "g");
+        RGBA_8888.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 8, "b");
+        RGBA_8888.mEntries[3] = new Entry(DataType.UNSIGNED, DataKind.ALPHA, true, 8, "a");
+        RGBA_8888.init(rs);
+
+        INDEX_16.mEntries = new Entry[1];
+        INDEX_16.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.INDEX, false, 16, "index");
+        INDEX_16.init(rs);
+
+        XY_F32.mEntries = new Entry[2];
+        XY_F32.mEntries[0] = new Entry(DataType.FLOAT, DataKind.X, false, 32, "x");
+        XY_F32.mEntries[1] = new Entry(DataType.FLOAT, DataKind.Y, false, 32, "y");
+        XY_F32.init(rs);
+
+        XYZ_F32.mEntries = new Entry[3];
+        XYZ_F32.mEntries[0] = new Entry(DataType.FLOAT, DataKind.X, false, 32, "x");
+        XYZ_F32.mEntries[1] = new Entry(DataType.FLOAT, DataKind.Y, false, 32, "y");
+        XYZ_F32.mEntries[2] = new Entry(DataType.FLOAT, DataKind.Z, false, 32, "z");
+        XYZ_F32.init(rs);
+
+        ST_XY_F32.mEntries = new Entry[4];
+        ST_XY_F32.mEntries[0] = new Entry(DataType.FLOAT, DataKind.S, false, 32, "s");
+        ST_XY_F32.mEntries[1] = new Entry(DataType.FLOAT, DataKind.T, false, 32, "t");
+        ST_XY_F32.mEntries[2] = new Entry(DataType.FLOAT, DataKind.X, false, 32, "x");
+        ST_XY_F32.mEntries[3] = new Entry(DataType.FLOAT, DataKind.Y, false, 32, "y");
+        ST_XY_F32.init(rs);
+
+        ST_XYZ_F32.mEntries = new Entry[5];
+        ST_XYZ_F32.mEntries[0] = new Entry(DataType.FLOAT, DataKind.S, false, 32, "s");
+        ST_XYZ_F32.mEntries[1] = new Entry(DataType.FLOAT, DataKind.T, false, 32, "t");
+        ST_XYZ_F32.mEntries[2] = new Entry(DataType.FLOAT, DataKind.X, false, 32, "x");
+        ST_XYZ_F32.mEntries[3] = new Entry(DataType.FLOAT, DataKind.Y, false, 32, "y");
+        ST_XYZ_F32.mEntries[4] = new Entry(DataType.FLOAT, DataKind.Z, false, 32, "z");
+        ST_XYZ_F32.init(rs);
+
+        NORM_XYZ_F32.mEntries = new Entry[6];
+        NORM_XYZ_F32.mEntries[0] = new Entry(DataType.FLOAT, DataKind.NX, false, 32, "nx");
+        NORM_XYZ_F32.mEntries[1] = new Entry(DataType.FLOAT, DataKind.NY, false, 32, "ny");
+        NORM_XYZ_F32.mEntries[2] = new Entry(DataType.FLOAT, DataKind.NZ, false, 32, "nz");
+        NORM_XYZ_F32.mEntries[3] = new Entry(DataType.FLOAT, DataKind.X, false, 32, "x");
+        NORM_XYZ_F32.mEntries[4] = new Entry(DataType.FLOAT, DataKind.Y, false, 32, "y");
+        NORM_XYZ_F32.mEntries[5] = new Entry(DataType.FLOAT, DataKind.Z, false, 32, "z");
+        NORM_XYZ_F32.init(rs);
+
+        NORM_ST_XYZ_F32.mEntries = new Entry[8];
+        NORM_ST_XYZ_F32.mEntries[0] = new Entry(DataType.FLOAT, DataKind.NX, false, 32, "nx");
+        NORM_ST_XYZ_F32.mEntries[1] = new Entry(DataType.FLOAT, DataKind.NY, false, 32, "ny");
+        NORM_ST_XYZ_F32.mEntries[2] = new Entry(DataType.FLOAT, DataKind.NZ, false, 32, "nz");
+        NORM_ST_XYZ_F32.mEntries[3] = new Entry(DataType.FLOAT, DataKind.S, false, 32, "s");
+        NORM_ST_XYZ_F32.mEntries[4] = new Entry(DataType.FLOAT, DataKind.T, false, 32, "t");
+        NORM_ST_XYZ_F32.mEntries[5] = new Entry(DataType.FLOAT, DataKind.X, false, 32, "x");
+        NORM_ST_XYZ_F32.mEntries[6] = new Entry(DataType.FLOAT, DataKind.Y, false, 32, "y");
+        NORM_ST_XYZ_F32.mEntries[7] = new Entry(DataType.FLOAT, DataKind.Z, false, 32, "z");
+        NORM_ST_XYZ_F32.init(rs);
+
+        rs.nInitElements(A_8.mID, RGBA_4444.mID, RGBA_8888.mID, RGB_565.mID);
     }
 
 
@@ -121,27 +230,13 @@
         }
     }
 
-
-    Element(int predef, int size) {
+    Element() {
         super(null);
         mID = 0;
-        mPredefinedID = predef;
-        mIsPredefined = true;
-        mSize = size;
-    }
-
-    Element(int id, RenderScript rs, int size) {
-        super(rs);
-        mID = id;
-        mPredefinedID = 0;
-        mIsPredefined = false;
-        mSize = size;
+        mSize = 0;
     }
 
     public void destroy() throws IllegalStateException {
-        if(mIsPredefined) {
-            throw new IllegalStateException("Attempting to destroy a predefined Element.");
-        }
         super.destroy();
     }
 
@@ -166,27 +261,41 @@
         return b.create();
     }
 
+    static synchronized void internalCreate(RenderScript rs, Element e) {
+        rs.nElementBegin();
+        int bits = 0;
+        for (int ct=0; ct < e.mEntries.length; ct++) {
+            Entry en = e.mEntries[ct];
+            if(en.mElement !=  null) {
+                //rs.nElementAdd(en.mElement.mID);
+            } else {
+                int norm = 0;
+                if (en.mIsNormalized) {
+                    norm = 1;
+                }
+                rs.nElementAdd(en.mKind.mID, en.mType.mID, norm, en.mBits, en.mName);
+                bits += en.mBits;
+            }
+        }
+        e.mID = rs.nElementCreate();
+        e.mSize = (bits + 7) >> 3;
+    }
+
+    void init(RenderScript rs) {
+        mRS = rs;
+        internalCreate(mRS, this);
+    }
+
 
     public static class Builder {
         RenderScript mRS;
         Entry[] mEntries;
         int mEntryCount;
-        int mSizeBits;
-
-        private class Entry {
-            Element mElement;
-            Element.DataType mType;
-            Element.DataKind mKind;
-            boolean mIsNormalized;
-            int mBits;
-            String mName;
-        }
 
         public Builder(RenderScript rs) {
             mRS = rs;
             mEntryCount = 0;
             mEntries = new Entry[8];
-            mSizeBits = 0;
         }
 
         void addEntry(Entry e) {
@@ -200,24 +309,13 @@
         }
 
         public Builder add(Element e) throws IllegalArgumentException {
-            if(!e.mIsPredefined) {
-                throw new IllegalArgumentException("add requires a predefined Element.");
-            }
-            Entry en = new Entry();
-            en.mElement = e;
+            Entry en = new Entry(e, e.mSize * 8);
             addEntry(en);
-            mSizeBits += e.mSize * 8;
             return this;
         }
 
         public Builder add(Element.DataType dt, Element.DataKind dk, boolean isNormalized, int bits, String name) {
-            Entry en = new Entry();
-            en.mType = dt;
-            en.mKind = dk;
-            en.mIsNormalized = isNormalized;
-            en.mBits = bits;
-            en.mName = name;
-            mSizeBits += bits;
+            Entry en = new Entry(dt, dk, isNormalized, bits, name);
             addEntry(en);
             return this;
         }
@@ -345,26 +443,12 @@
             return this;
         }
 
-        static synchronized Element internalCreate(RenderScript rs, Builder b) {
-            rs.nElementBegin();
-            for (int ct=0; ct < b.mEntryCount; ct++) {
-                Entry en = b.mEntries[ct];
-                if(en.mElement !=  null) {
-                    rs.nElementAddPredefined(en.mElement.mPredefinedID);
-                } else {
-                    int norm = 0;
-                    if (en.mIsNormalized) {
-                        norm = 1;
-                    }
-                    rs.nElementAdd(en.mKind.mID, en.mType.mID, norm, en.mBits, en.mName);
-                }
-            }
-            int id = rs.nElementCreate();
-            return new Element(id, rs, (b.mSizeBits + 7) >> 3);
-        }
-
         public Element create() {
-            return internalCreate(mRS, this);
+            Element e = new Element();
+            e.mEntries = new Entry[mEntryCount];
+            java.lang.System.arraycopy(mEntries, 0, e.mEntries, 0, mEntryCount);
+            e.init(mRS);
+            return e;
         }
     }
 
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index bd345e5..6f5b67e 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -57,6 +57,8 @@
         }
     }
 
+    native void nInitElements(int a8, int rgba4444, int rgba8888, int rgb565);
+
     native int  nDeviceCreate();
     native void nDeviceDestroy(int dev);
     native int  nContextCreate(int dev, Surface sur, int ver, boolean useDepth);
@@ -78,10 +80,8 @@
     native int  nFileOpen(byte[] name);
 
     native void nElementBegin();
-    native void nElementAddPredefined(int predef);
     native void nElementAdd(int kind, int type, int norm, int bits, String s);
     native int  nElementCreate();
-    native int  nElementGetPredefined(int predef);
 
     native void nTypeBegin(int elementID);
     native void nTypeAdd(int dim, int val);
@@ -90,7 +90,6 @@
     native void nTypeSetupFields(Type t, int[] types, int[] bits, Field[] IDs);
 
     native int  nAllocationCreateTyped(int type);
-    native int  nAllocationCreatePredefSized(int predef, int count);
     native int  nAllocationCreateSized(int elem, int count);
     native int  nAllocationCreateFromBitmap(int dstFmt, boolean genMips, Bitmap bmp);
     native int  nAllocationCreateFromBitmapBoxed(int dstFmt, boolean genMips, Bitmap bmp);
@@ -203,7 +202,7 @@
 
         // TODO: This should be protected by a lock
         if(!mElementsInitialized) {
-            Element.init(this);
+            Element.initPredefined(this);
             mElementsInitialized = true;
         }
     }
@@ -227,7 +226,6 @@
     }
 
     public void triangleMeshBegin(Element vertex, Element index) {
-        Log.e("rs", "vtx " + vertex.toString() + "  " + vertex.mID + "  " + vertex.mPredefinedID);
         nTriangleMeshBegin(vertex.mID, index.mID);
     }
 
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 62c3914..a94ccb1 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -58,6 +58,11 @@
 static jfieldID gNativeBitmapID = 0;
 static jfieldID gTypeNativeCache = 0;
 
+static RsElement g_A_8 = NULL;
+static RsElement g_RGBA_4444 = NULL;
+static RsElement g_RGBA_8888 = NULL;
+static RsElement g_RGB_565 = NULL;
+
 static void _nInit(JNIEnv *_env, jclass _this)
 {
     gContextId             = _env->GetFieldID(_this, "mContext", "I");
@@ -69,6 +74,13 @@
     gTypeNativeCache = _env->GetFieldID(typeClass, "mNativeCache", "I");
 }
 
+static void nInitElements(JNIEnv *_env, jobject _this, jint a8, jint rgba4444, jint rgba8888, jint rgb565)
+{
+    g_A_8 = reinterpret_cast<RsElement>(a8);
+    g_RGBA_4444 = reinterpret_cast<RsElement>(rgba4444);
+    g_RGBA_8888 = reinterpret_cast<RsElement>(rgba8888);
+    g_RGB_565 = reinterpret_cast<RsElement>(rgb565);
+}
 
 // ---------------------------------------------------------------------------
 
@@ -167,13 +179,6 @@
     rsElementBegin(con);
 }
 
-static void
-nElementAddPredefined(JNIEnv *_env, jobject _this, jint predef)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nElementAddPredefined, con(%p), predef(%i)", con, predef);
-    rsElementAddPredefined(con, (RsElementPredefined)predef);
-}
 
 static void
 nElementAdd(JNIEnv *_env, jobject _this, jint kind, jint type, jint norm, jint bits, jstring name)
@@ -198,14 +203,6 @@
     return (jint)rsElementCreate(con);
 }
 
-static jint
-nElementGetPredefined(JNIEnv *_env, jobject _this, jint predef)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nElementGetPredefined, con(%p) predef(%i)", con, predef);
-    return (jint)rsElementGetPredefined(con, (RsElementPredefined)predef);
-}
-
 // -----------------------------------
 
 static void
@@ -328,14 +325,6 @@
 }
 
 static jint
-nAllocationCreatePredefSized(JNIEnv *_env, jobject _this, jint predef, jint count)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nAllocationCreatePredefSized, con(%p), predef(%i), count(%i)", con, predef, count);
-    return (jint) rsAllocationCreatePredefSized(con, (RsElementPredefined)predef, count);
-}
-
-static jint
 nAllocationCreateSized(JNIEnv *_env, jobject _this, jint e, jint count)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
@@ -359,24 +348,24 @@
     rsAllocationUploadToBufferObject(con, (RsAllocation)a);
 }
 
-static RsElementPredefined SkBitmapToPredefined(SkBitmap::Config cfg)
+static RsElement SkBitmapToPredefined(SkBitmap::Config cfg)
 {
     switch (cfg) {
     case SkBitmap::kA8_Config:
-        return RS_ELEMENT_A_8;
+        return g_A_8;
     case SkBitmap::kARGB_4444_Config:
-        return RS_ELEMENT_RGBA_4444;
+        return g_RGBA_4444;
     case SkBitmap::kARGB_8888_Config:
-        return RS_ELEMENT_RGBA_8888;
+        return g_RGBA_8888;
     case SkBitmap::kRGB_565_Config:
-        return RS_ELEMENT_RGB_565;
+        return g_RGB_565;
 
     default:
         break;
     }
     // If we don't have a conversion mark it as a user type.
     LOGE("Unsupported bitmap type");
-    return RS_ELEMENT_USER_U8;
+    return NULL;
 }
 
 static int
@@ -388,14 +377,13 @@
     const SkBitmap& bitmap(*nativeBitmap);
     SkBitmap::Config config = bitmap.getConfig();
 
-    RsElementPredefined e = SkBitmapToPredefined(config);
-
-    if (e != RS_ELEMENT_USER_U8) {
+    RsElement e = SkBitmapToPredefined(config);
+    if (e) {
         bitmap.lockPixels();
         const int w = bitmap.width();
         const int h = bitmap.height();
         const void* ptr = bitmap.getPixels();
-        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElementPredefined)dstFmt, e, genMips, ptr);
+        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
         bitmap.unlockPixels();
         return id;
     }
@@ -414,14 +402,14 @@
 
     SkBitmap::Config config = bitmap.getConfig();
 
-    RsElementPredefined e = SkBitmapToPredefined(config);
+    RsElement e = SkBitmapToPredefined(config);
 
-    if (e != RS_ELEMENT_USER_U8) {
+    if (e) {
         bitmap.lockPixels();
         const int w = bitmap.width();
         const int h = bitmap.height();
         const void* ptr = bitmap.getPixels();
-        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElementPredefined)dstFmt, e, genMips, ptr);
+        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
         bitmap.unlockPixels();
         return id;
     }
@@ -437,14 +425,14 @@
     const SkBitmap& bitmap(*nativeBitmap);
     SkBitmap::Config config = bitmap.getConfig();
 
-    RsElementPredefined e = SkBitmapToPredefined(config);
+    RsElement e = SkBitmapToPredefined(config);
 
-    if (e != RS_ELEMENT_USER_U8) {
+    if (e) {
         bitmap.lockPixels();
         const int w = bitmap.width();
         const int h = bitmap.height();
         const void* ptr = bitmap.getPixels();
-        jint id = (jint)rsAllocationCreateFromBitmapBoxed(con, w, h, (RsElementPredefined)dstFmt, e, genMips, ptr);
+        jint id = (jint)rsAllocationCreateFromBitmapBoxed(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
         bitmap.unlockPixels();
         return id;
     }
@@ -1244,6 +1232,8 @@
 
 static JNINativeMethod methods[] = {
 {"_nInit",                         "()V",                                  (void*)_nInit },
+{"nInitElements",                  "(IIII)V",                              (void*)nInitElements },
+
 {"nDeviceCreate",                  "()I",                                  (void*)nDeviceCreate },
 {"nDeviceDestroy",                 "(I)V",                                 (void*)nDeviceDestroy },
 {"nContextCreate",                 "(ILandroid/view/Surface;IZ)I",         (void*)nContextCreate },
@@ -1255,10 +1245,8 @@
 {"nFileOpen",                      "([B)I",                                (void*)nFileOpen },
 
 {"nElementBegin",                  "()V",                                  (void*)nElementBegin },
-{"nElementAddPredefined",          "(I)V",                                 (void*)nElementAddPredefined },
 {"nElementAdd",                    "(IIIILjava/lang/String;)V",            (void*)nElementAdd },
 {"nElementCreate",                 "()I",                                  (void*)nElementCreate },
-{"nElementGetPredefined",          "(I)I",                                 (void*)nElementGetPredefined },
 
 {"nTypeBegin",                     "(I)V",                                 (void*)nTypeBegin },
 {"nTypeAdd",                       "(II)V",                                (void*)nTypeAdd },
@@ -1267,7 +1255,6 @@
 {"nTypeSetupFields",               "(Landroid/renderscript/Type;[I[I[Ljava/lang/reflect/Field;)V", (void*)nTypeSetupFields },
 
 {"nAllocationCreateTyped",         "(I)I",                                 (void*)nAllocationCreateTyped },
-{"nAllocationCreatePredefSized",   "(II)I",                                (void*)nAllocationCreatePredefSized },
 {"nAllocationCreateSized",         "(II)I",                                (void*)nAllocationCreateSized },
 {"nAllocationCreateFromBitmap",    "(IZLandroid/graphics/Bitmap;)I",       (void*)nAllocationCreateFromBitmap },
 {"nAllocationCreateFromBitmapBoxed","(IZLandroid/graphics/Bitmap;)I",      (void*)nAllocationCreateFromBitmapBoxed },
diff --git a/libs/rs/java/Fall/res/raw/fall.c b/libs/rs/java/Fall/res/raw/fall.c
index c09f43c..346006c 100644
--- a/libs/rs/java/Fall/res/raw/fall.c
+++ b/libs/rs/java/Fall/res/raw/fall.c
@@ -47,6 +47,20 @@
 // The higher, the smaller the ripple
 #define RIPPLE_HEIGHT 10.0f
 
+float g_SkyOffsetX;
+float g_SkyOffsetY;
+
+struct vert_s {
+    float nx;
+    float ny;
+    float nz;
+    float s;
+    float t;
+    float x;
+    float y;
+    float z;
+};
+
 int offset(int x, int y, int width) {
     return x + 1 + (y + 1) * (width + 2);
 }
@@ -150,8 +164,8 @@
     int *map = loadArrayI32(RSID_REFRACTION_MAP, 0);
     float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh);
 
-    float fw = (float) width;
-    float fh = (float) height;
+    float fw = 1.f / width;
+    float fh = 1.f / height;
     float fy = (1.0f / 512.0f) * (1.0f / RIPPLE_HEIGHT);
 
     int h = height - 1;
@@ -175,8 +189,8 @@
             if (v >= height) v = height - 1;
 
             int index = (offset + w) << 3;
-            vertices[index + 3] = u / fw;
-            vertices[index + 4] = v / fh;
+            vertices[index + 3] = u * fw;
+            vertices[index + 4] = v * fh;
 
             // Update Z coordinate of the vertex
             vertices[index + 7] = dy * fy;
@@ -196,76 +210,26 @@
         int x = 0;
         int yOffset = y * width;
         for ( ; x < width; x += 1) {
-            int o = (yOffset + x) << 3;
-            int o1 = o + 8;
-            int ow = o + w8;
+            int o = ((yOffset + x) << 3);
+            int o1 = o + 8 + 5;
+            int ow = o + w8 + 5;
             int ow1 = ow + 8;
 
-            // V1
-            float v1x = vertices[o + 5];
-            float v1y = vertices[o + 6];
-            float v1z = vertices[o + 7];
-
-            // V2
-            float v2x = vertices[o1 + 5];
-            float v2y = vertices[o1 + 6];
-            float v2z = vertices[o1 + 7];
-
-            // V3
-            float v3x = vertices[ow + 5];
-            float v3y = vertices[ow + 6];
-            float v3z = vertices[ow + 7];
-
-            // N1
-            float n1x = v2x - v1x;
-            float n1y = v2y - v1y;
-            float n1z = v2z - v1z;
-
-            // N2
-            float n2x = v3x - v1x;
-            float n2y = v3y - v1y;
-            float n2z = v3z - v1z;
-
-            // N1 x N2
-            float n3x = n1y * n2z - n1z * n2y;
-            float n3y = n1z * n2x - n1x * n2z;
-            float n3z = n1x * n2y - n1y * n2x;
-
-            // Normalize
-            float len = 1.0f / magf3(n3x, n3y, n3z);
-            n3x *= len;
-            n3y *= len;
-            n3z *= len;
-
-            // V2
-            v2x = vertices[ow1 + 5];
-            v2y = vertices[ow1 + 6];
-            v2z = vertices[ow1 + 7];
-
-            // N1
-            n1x = v2x - v1x;
-            n1y = v2y - v1y;
-            n1z = v2z - v1z;
-
-            // N2
-            n2x = v3x - v1x;
-            n2y = v3y - v1y;
-            n2z = v3z - v1z;
+            struct vec3_s n1, n2, n3;
+            vec3Sub(&n1, (struct vec3_s *)(vertices + o1 + 5), (struct vec3_s *)(vertices + o + 5));
+            vec3Sub(&n2, (struct vec3_s *)(vertices + ow + 5), (struct vec3_s *)(vertices + o + 5));
+            vec3Cross(&n3, &n1, &n2);
+            vec3Norm(&n3);
 
             // Average of previous normal and N1 x N2
-            n3x = n3x * 0.5f + (n1y * n2z - n1z * n2y) * 0.5f;
-            n3y = n3y * 0.5f + (n1z * n2x - n1x * n2z) * 0.5f;
-            n3z = n3z * 0.5f + (n1x * n2y - n1y * n2x) * 0.5f;
+            vec3Sub(&n1, (struct vec3_s *)(vertices + ow1 + 5), (struct vec3_s *)(vertices + o + 5));
+            vec3Cross(&n2, &n1, &n2);
+            vec3Add(&n3, &n3, &n2);
+            vec3Norm(&n3);
 
-            // Normalize
-            len = 1.0f / magf3(n3x, n3y, n3z);
-            n3x *= len;
-            n3y *= len;
-            n3z *= len;
-
-            vertices[o + 0] = n3x;
-            vertices[o + 1] = n3y;
-            vertices[o + 2] = -n3z;
+            vertices[o + 0] = n3.x;
+            vertices[o + 1] = n3.y;
+            vertices[o + 2] = -n3.z;
 
             // reset Z
             //vertices[(yOffset + x) << 3 + 7] = 0.0f;
@@ -433,15 +397,15 @@
     bindProgramFragmentStore(NAMED_PFSLeaf);
     bindTexture(NAMED_PFSky, 0, NAMED_TSky);
 
-    float x = State->skyOffsetX + State->skySpeedX;
-    float y = State->skyOffsetY + State->skySpeedY;
+    float x = g_SkyOffsetX + State->skySpeedX;
+    float y = g_SkyOffsetY + State->skySpeedY;
 
     if (x > 1.0f) x = 0.0f;
     if (x < -1.0f) x = 0.0f;
     if (y > 1.0f) y = 0.0f;
 
-    storeF(RSID_STATE, OFFSETOF_WorldState_skyOffsetX, x);
-    storeF(RSID_STATE, OFFSETOF_WorldState_skyOffsetY, y);
+    g_SkyOffsetX = x;
+    g_SkyOffsetY = y;
 
     float matrix[16];
     matrixLoadTranslate(matrix, x, y, 0.0f);
@@ -509,7 +473,7 @@
     drawRiverbed();
     drawSky();
     drawLighting();
-    drawLeaves();
+    //drawLeaves();
     //drawNormals();
 
     return 1;
diff --git a/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java b/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java
index 8a33d66..33aa9ab 100644
--- a/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java
+++ b/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java
@@ -44,7 +44,7 @@
     private static final int MESH_RESOLUTION = 48;
 
     private static final int RSID_STATE = 0;
-    
+
     private static final int TEXTURES_COUNT = 3;
     private static final int LEAVES_TEXTURES_COUNT = 4;
     private static final int RSID_TEXTURE_RIVERBED = 0;
@@ -52,7 +52,7 @@
     private static final int RSID_TEXTURE_SKY = 2;
 
     private static final int RSID_RIPPLE_MAP = 1;
-    
+
     private static final int RSID_REFRACTION_MAP = 2;
 
     private static final int RSID_LEAVES = 3;
@@ -70,7 +70,21 @@
     private static final int LEAF_STRUCT_DELTAX = 9;
     private static final int LEAF_STRUCT_DELTAY = 10;
 
-    private static final int RSID_DROP = 4;    
+    class Leaf {
+        float x;
+        float y;
+        float scale;
+        float angle;
+        float spin;
+        float u1;
+        float u2;
+        float altitude;
+        float rippled;
+        float deltaX;
+        float deltaY;
+    }
+
+    private static final int RSID_DROP = 4;
 
     private Resources mResources;
     private RenderScript mRS;
@@ -175,10 +189,10 @@
 
         float quadWidth = 2.0f / (float) wResolution;
         float quadHeight = glHeight / (float) hResolution;
-        
+
         wResolution += 2;
-        hResolution += 2;        
-        
+        hResolution += 2;
+
         for (int y = 0; y <= hResolution; y++) {
             final boolean shift = (y & 0x1) == 0;
             final float yOffset = y * quadHeight - glHeight / 2.0f - quadHeight;
@@ -267,12 +281,10 @@
         public int leavesCount;
         public float glWidth;
         public float glHeight;
-        public float skyOffsetX;
-        public float skyOffsetY;
         public float skySpeedX;
         public float skySpeedY;
     }
-    
+
     static class DropState {
         public int dropX;
         public int dropY;
@@ -295,11 +307,11 @@
         mStateType = Type.createFromClass(mRS, WorldState.class, 1, "WorldState");
         mState = Allocation.createTyped(mRS, mStateType);
         mState.data(worldState);
-        
+
         mDrop = new DropState();
         mDrop.dropX = -1;
         mDrop.dropY = -1;
-        
+
         mDropType = Type.createFromClass(mRS, DropState.class, 1, "DropState");
         mDropState = Allocation.createTyped(mRS, mDropType);
         mDropState.data(mDrop);
@@ -346,7 +358,7 @@
         final Allocation allocation = Allocation.createFromBitmap(mRS, b, RGBA_8888, false);
         allocation.setName(name);
         return allocation;
-    }    
+    }
 
     private void createProgramFragment() {
         Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
@@ -368,7 +380,7 @@
         mPfLighting = builder.create();
         mPfLighting.setName("PFLighting");
         mPfLighting.bindSampler(sampler, 0);
-        
+
         builder = new ProgramFragment.Builder(mRS, null, null);
         builder.setTexEnable(true, 0);
         builder.setTexEnvMode(MODULATE, 0);
@@ -407,7 +419,7 @@
         mPvLight = builder.create();
         mPvLight.bindAllocation(pvOrthoAlloc);
         mPvLight.setName("PVLight");
-        
+
         builder = new ProgramVertex.Builder(mRS, null, null);
         builder.setTextureMatrixEnable(true);
         mPvSky = builder.create();
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index cb4dd00..ac2e738 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -39,10 +39,6 @@
 ElementBegin {
 }
 
-ElementAddPredefined {
-	param RsElementPredefined predef
-	}
-
 ElementAdd {
 	param RsDataKind dataKind
 	param RsDataType dataType
@@ -99,8 +95,8 @@
 AllocationCreateFromBitmap {
 	param uint32_t width
 	param uint32_t height
-	param RsElementPredefined dstFmt
-	param RsElementPredefined srcFmt
+	param RsElement dstFmt
+	param RsElement srcFmt
 	param bool genMips
 	param const void * data
 	ret RsAllocation
@@ -109,8 +105,8 @@
 AllocationCreateFromBitmapBoxed {
 	param uint32_t width
 	param uint32_t height
-	param RsElementPredefined dstFmt
-	param RsElementPredefined srcFmt
+	param RsElement dstFmt
+	param RsElement srcFmt
 	param bool genMips
 	param const void * data
 	ret RsAllocation
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 1f49ca1..c267e16 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -310,40 +310,54 @@
     }
 }
 
-static ElementConverter_t pickConverter(RsElementPredefined dstFmt, RsElementPredefined srcFmt)
+static ElementConverter_t pickConverter(const Element *dst, const Element *src)
 {
-    if ((dstFmt == RS_ELEMENT_RGB_565) &&
-        (srcFmt == RS_ELEMENT_RGB_565)) {
-        return elementConverter_cpy_16;
+    GLenum srcGLType = src->getGLType();
+    GLenum srcGLFmt = src->getGLFormat();
+    GLenum dstGLType = dst->getGLType();
+    GLenum dstGLFmt = dst->getGLFormat();
+
+    if (srcGLFmt == dstGLFmt && srcGLType == dstGLType) {
+        switch(dst->getSizeBytes()) {
+        case 4:
+            return elementConverter_cpy_32;
+        case 2:
+            return elementConverter_cpy_16;
+        case 1:
+            return elementConverter_cpy_8;
+        }
     }
 
-    if ((dstFmt == RS_ELEMENT_RGB_565) &&
-        (srcFmt == RS_ELEMENT_RGB_888)) {
+    if (srcGLType == GL_UNSIGNED_BYTE &&
+        srcGLFmt == GL_RGB &&
+        dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
+        dstGLType == GL_RGB) {
+
         return elementConverter_888_to_565;
     }
 
-    if ((dstFmt == RS_ELEMENT_RGB_565) &&
-        (srcFmt == RS_ELEMENT_RGBA_8888)) {
+    if (srcGLType == GL_UNSIGNED_BYTE &&
+        srcGLFmt == GL_RGBA &&
+        dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
+        dstGLType == GL_RGB) {
+
         return elementConverter_8888_to_565;
     }
 
-    if ((dstFmt == RS_ELEMENT_RGBA_8888) &&
-        (srcFmt == RS_ELEMENT_RGBA_8888)) {
-        return elementConverter_cpy_32;
-    }
-
-    LOGE("pickConverter, unsuported combo, src %i,  dst %i", srcFmt, dstFmt);
+    LOGE("pickConverter, unsuported combo, src %p,  dst %p", src, dst);
     return 0;
 }
 
 
-RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElementPredefined dstFmt, RsElementPredefined srcFmt,  bool genMips, const void *data)
+RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src,  bool genMips, const void *data)
 {
+    const Element *src = static_cast<const Element *>(_src);
+    const Element *dst = static_cast<const Element *>(_dst);
     rsAssert(!(w & (w-1)));
     rsAssert(!(h & (h-1)));
 
     //LOGE("rsi_AllocationCreateFromBitmap %i %i %i %i %i", w, h, dstFmt, srcFmt, genMips);
-    rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, dstFmt));
+    rsi_TypeBegin(rsc, _dst);
     rsi_TypeAdd(rsc, RS_DIMENSION_X, w);
     rsi_TypeAdd(rsc, RS_DIMENSION_Y, h);
     if (genMips) {
@@ -359,7 +373,7 @@
     }
     texAlloc->incUserRef();
 
-    ElementConverter_t cvt = pickConverter(dstFmt, srcFmt);
+    ElementConverter_t cvt = pickConverter(dst, src);
     cvt(texAlloc->getPtr(), data, w * h);
 
     if (genMips) {
@@ -375,21 +389,18 @@
     return texAlloc;
 }
 
-static uint32_t fmtToBits(RsElementPredefined fmt)
+RsAllocation rsi_AllocationCreateFromBitmapBoxed(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data)
 {
-    return 16;
-}
-
-RsAllocation rsi_AllocationCreateFromBitmapBoxed(Context *rsc, uint32_t w, uint32_t h, RsElementPredefined dstFmt, RsElementPredefined srcFmt, bool genMips, const void *data)
-{
+    const Element *srcE = static_cast<const Element *>(_src);
+    const Element *dstE = static_cast<const Element *>(_dst);
     uint32_t w2 = rsHigherPow2(w);
     uint32_t h2 = rsHigherPow2(h);
 
     if ((w2 == w) && (h2 == h)) {
-        return rsi_AllocationCreateFromBitmap(rsc, w, h, dstFmt, srcFmt, genMips, data);
+        return rsi_AllocationCreateFromBitmap(rsc, w, h, _dst, _src, genMips, data);
     }
 
-    uint32_t bpp = fmtToBits(srcFmt) >> 3;
+    uint32_t bpp = srcE->getSizeBytes();
     size_t size = w2 * h2 * bpp;
     uint8_t *tmp = static_cast<uint8_t *>(malloc(size));
     memset(tmp, 0, size);
@@ -401,7 +412,7 @@
         src += w * bpp;
     }
 
-    RsAllocation ret = rsi_AllocationCreateFromBitmap(rsc, w2, h2, dstFmt, srcFmt, genMips, tmp);
+    RsAllocation ret = rsi_AllocationCreateFromBitmap(rsc, w2, h2, _dst, _src, genMips, tmp);
     free(tmp);
     return ret;
 
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index c132915..04f6e07 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -184,10 +184,10 @@
 
     LOGV("RS: Frame (%lli),   Script %2.1f (%lli),  Clear & Swap %2.1f (%lli),  Idle %2.1f (%lli),  Internal %2.1f (%lli)",
          frame / 1000000,
-         100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
-         100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000,
          100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimers[RS_TIMER_SCRIPT] / 1000000,
-         100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimers[RS_TIMER_CLEAR_SWAP] / 1000000);
+         100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimers[RS_TIMER_CLEAR_SWAP] / 1000000,
+         100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
+         100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000);
 }
 
 void Context::setupCheck()
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 9d9eb1b..8230cbc 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -286,6 +286,10 @@
     char buf[256];
     String8 tmp;
 
+    str->append("struct vec2_s {float x; float y;};");
+    str->append("struct vec3_s {float x; float y; float z;};");
+    str->append("struct vec4_s {float x; float y; float z; float w;};");
+
     for (size_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
         const Type *t = mConstantBufferTypes[ct].get();
         if (!t) {
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 84a39aa..5b19f17 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -36,6 +36,23 @@
     Context * rsc = tls->mContext; \
     ScriptC * sc = (ScriptC *) tls->mScript
 
+typedef struct {
+    float x;
+    float y;
+    float z;
+} vec3_t;
+
+typedef struct {
+    float x;
+    float y;
+    float z;
+    float w;
+} vec4_t;
+
+typedef struct {
+    float x;
+    float y;
+} vec2_t;
 
 //////////////////////////////////////////////////////////////////////////////
 // IO routines
@@ -161,6 +178,60 @@
     memcpy(&f[offset], m, sizeof(rsc_Matrix));
 }
 
+//////////////////////////////////////////////////////////////////////////////
+// Vec3 routines
+//////////////////////////////////////////////////////////////////////////////
+
+static void SC_vec3Norm(vec3_t *v)
+{
+    float len = sqrtf(v->x * v->x + v->y * v->y + v->z * v->z);
+    len = 1 / len;
+    v->x *= len;
+    v->y *= len;
+    v->z *= len;
+}
+
+static float SC_vec3Length(const vec3_t *v)
+{
+    return sqrtf(v->x * v->x + v->y * v->y + v->z * v->z);
+}
+
+static void SC_vec3Add(vec3_t *dest, const vec3_t *lhs, const vec3_t *rhs)
+{
+    dest->x = lhs->x + rhs->x;
+    dest->y = lhs->y + rhs->y;
+    dest->z = lhs->z + rhs->z;
+}
+
+static void SC_vec3Sub(vec3_t *dest, const vec3_t *lhs, const vec3_t *rhs)
+{
+    dest->x = lhs->x - rhs->x;
+    dest->y = lhs->y - rhs->y;
+    dest->z = lhs->z - rhs->z;
+}
+
+static void SC_vec3Cross(vec3_t *dest, const vec3_t *lhs, const vec3_t *rhs)
+{
+    float x = lhs->y * rhs->z  - lhs->z * rhs->y;
+    float y = lhs->z * rhs->x  - lhs->x * rhs->z;
+    float z = lhs->x * rhs->y  - lhs->y * rhs->x;
+    dest->x = x;
+    dest->y = y;
+    dest->z = z;
+}
+
+static float SC_vec3Dot(const vec3_t *lhs, const vec3_t *rhs)
+{
+    return lhs->x * rhs->x + lhs->y * rhs->y + lhs->z * rhs->z;
+}
+
+static void SC_vec3Scale(vec3_t *lhs, float scale)
+{
+    lhs->x *= scale;
+    lhs->y *= scale;
+    lhs->z *= scale;
+}
+
 
 //////////////////////////////////////////////////////////////////////////////
 // Math routines
@@ -175,15 +246,15 @@
     const float A =   1.0f / (2.0f * M_PI);
     const float B = -16.0f;
     const float C =   8.0f;
-    
+
     // scale angle for easy argument reduction
     x *= A;
-    
+
     if (fabsf(x) >= 0.5f) {
         // argument reduction
         x = x - ceilf(x + 0.5f) + 1.0f;
     }
-    
+
     const float y = B * x * fabsf(x) + C * x;
     return 0.2215f * (y * fabsf(y) - y) + y;
 }
@@ -195,15 +266,15 @@
     const float A =   1.0f / (2.0f * M_PI);
     const float B = -16.0f;
     const float C =   8.0f;
-    
+
     // scale angle for easy argument reduction
     x *= A;
-    
+
     if (fabsf(x) >= 0.5f) {
         // argument reduction
         x = x - ceilf(x + 0.5f) + 1.0f;
     }
-    
+
     const float y = B * x * fabsf(x) + C * x;
     return 0.2215f * (y * fabsf(y) - y) + y;
 }
@@ -1038,6 +1109,22 @@
     { "vec2Rand", (void *)&SC_vec2Rand,
         "void", "(float *vec, float maxLen)" },
 
+    // vec3
+    { "vec3Norm", (void *)&SC_vec3Norm,
+        "void", "(struct vec3_s *)" },
+    { "vec3Length", (void *)&SC_vec3Length,
+        "float", "(struct vec3_s *)" },
+    { "vec3Add", (void *)&SC_vec3Add,
+        "void", "(struct vec3_s *dest, struct vec3_s *lhs, struct vec3_s *rhs)" },
+    { "vec3Sub", (void *)&SC_vec3Sub,
+        "void", "(struct vec3_s *dest, struct vec3_s *lhs, struct vec3_s *rhs)" },
+    { "vec3Cross", (void *)&SC_vec3Cross,
+        "void", "(struct vec3_s *dest, struct vec3_s *lhs, struct vec3_s *rhs)" },
+    { "vec3Dot", (void *)&SC_vec3Dot,
+        "float", "(struct vec3_s *lhs, struct vec3_s *rhs)" },
+    { "vec3Scale", (void *)&SC_vec3Scale,
+        "void", "(struct vec3_s *lhs, float scale)" },
+
     // context
     { "bindProgramFragment", (void *)&SC_bindProgramFragment,
         "void", "(int)" },