Merge "Annotate Locations coming from mock providers"
diff --git a/api/current.txt b/api/current.txt
index 08e9e75..fc60f94 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -57,6 +57,7 @@
     field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
     field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
     field public static final java.lang.String GET_TASKS = "android.permission.GET_TASKS";
+    field public static final java.lang.String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO";
     field public static final java.lang.String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
     field public static final java.lang.String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
     field public static final java.lang.String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
@@ -2738,6 +2739,7 @@
     method public void onPrepareNavigateUpTaskStack(android.app.TaskStackBuilder);
     method public boolean onPrepareOptionsMenu(android.view.Menu);
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+    method public void onProvideAssistData(android.os.Bundle);
     method protected void onRestart();
     method protected void onRestoreInstanceState(android.os.Bundle);
     method protected void onResume();
@@ -3077,7 +3079,9 @@
     method public void onTerminate();
     method public void onTrimMemory(int);
     method public void registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
+    method public void registerOnProvideAssistData(android.app.Application.OnProvideAssistData);
     method public void unregisterActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
+    method public void unregisterOnProvideAssistData(android.app.Application.OnProvideAssistData);
   }
 
   public static abstract interface Application.ActivityLifecycleCallbacks {
@@ -3090,6 +3094,10 @@
     method public abstract void onActivityStopped(android.app.Activity);
   }
 
+  public static abstract interface Application.OnProvideAssistData {
+    method public abstract void onProvideAssistData(android.app.Activity, android.os.Bundle);
+  }
+
   public class ApplicationErrorReport implements android.os.Parcelable {
     ctor public ApplicationErrorReport();
     method public int describeContents();
@@ -5114,6 +5122,7 @@
     method public int bulkInsert(android.net.Uri, android.content.ContentValues[]);
     method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle);
     method public abstract int delete(android.net.Uri, java.lang.String, java.lang.String[]);
+    method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public final android.content.Context getContext();
     method public final android.content.pm.PathPermission[] getPathPermissions();
     method public final java.lang.String getReadPermission();
@@ -5901,6 +5910,8 @@
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final java.lang.String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
     field public static final deprecated java.lang.String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE";
+    field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT";
+    field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
     field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
     field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
     field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
@@ -6627,6 +6638,7 @@
     method public abstract void verifyPendingInstall(int, int);
     field public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; // 0x0
     field public static final int COMPONENT_ENABLED_STATE_DISABLED = 2; // 0x2
+    field public static final int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4; // 0x4
     field public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3; // 0x3
     field public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; // 0x1
     field public static final int DONT_KILL_APP = 1; // 0x1
@@ -6673,6 +6685,7 @@
     field public static final int GET_ACTIVITIES = 1; // 0x1
     field public static final int GET_CONFIGURATIONS = 16384; // 0x4000
     field public static final int GET_DISABLED_COMPONENTS = 512; // 0x200
+    field public static final int GET_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
     field public static final int GET_GIDS = 256; // 0x100
     field public static final int GET_INSTRUMENTATION = 16; // 0x10
     field public static final int GET_INTENT_FILTERS = 32; // 0x20
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 42c9d34..f0e3370 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -135,6 +135,11 @@
             return;
         }
 
+        if ("disable-until-used".equals(op)) {
+            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
+            return;
+        }
+
         if ("grant".equals(op)) {
             runGrantRevokePermission(true);
             return;
@@ -321,17 +326,8 @@
     @SuppressWarnings("unchecked")
     private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags, int userId)
             throws RemoteException {
-        final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
-        PackageInfo lastItem = null;
-        ParceledListSlice<PackageInfo> slice;
-
-        do {
-            final String lastKey = lastItem != null ? lastItem.packageName : null;
-            slice = pm.getInstalledPackages(flags, lastKey, userId);
-            lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
-        } while (!slice.isLastSlice());
-
-        return packageInfos;
+        ParceledListSlice<PackageInfo> slice = pm.getInstalledPackages(flags, userId);
+        return slice.getList();
     }
 
     /**
@@ -1187,6 +1183,8 @@
                 return "disabled";
             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
                 return "disabled-user";
+            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
+                return "disabled-until-used";
         }
         return "unknown";
     }
@@ -1468,6 +1466,7 @@
         System.err.println("       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
         System.err.println("       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
         System.err.println("       pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
+        System.err.println("       pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
         System.err.println("       pm grant PACKAGE PERMISSION");
         System.err.println("       pm revoke PACKAGE PERMISSION");
         System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 2337790..3602fc4 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -132,6 +132,12 @@
     public static final int DISPLAY_SHOW_CUSTOM = 0x10;
 
     /**
+     * Allow the title to wrap onto multiple lines if space is available
+     * @hide pending API approval
+     */
+    public static final int DISPLAY_TITLE_MULTIPLE_LINES = 0x20;
+
+    /**
      * Set the action bar into custom navigation mode, supplying a view
      * for custom navigation.
      *
@@ -680,6 +686,15 @@
     public Context getThemedContext() { return null; }
 
     /**
+     * Returns true if the Title field has been truncated during layout for lack
+     * of available space.
+     *
+     * @return true if the Title field has been truncated
+     * @hide pending API approval
+     */
+    public boolean isTitleTruncated() { return false; }
+
+    /**
      * Listener interface for ActionBar navigation events.
      */
     public interface OnNavigationListener {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d6ddeb6..18ccd53 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1346,6 +1346,20 @@
     }
 
     /**
+     * This is called when the user is requesting an assist, to build a full
+     * {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
+     * application.  You can override this method to place into the bundle anything
+     * you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
+     * of the assist Intent.  The default implementation does nothing.
+     *
+     * <p>This function will be called after any global assist callbacks that had
+     * been registered with {@link Application#registerOnProvideAssistData
+     * Application.registerOnProvideAssistData}.
+     */
+    public void onProvideAssistData(Bundle data) {
+    }
+
+    /**
      * Called when you are no longer visible to the user.  You will next
      * receive either {@link #onRestart}, {@link #onDestroy}, or nothing,
      * depending on later user activity.
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 61b2067..bc27a57d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1818,6 +1818,24 @@
             return true;
         }
 
+        case GET_TOP_ACTIVITY_EXTRAS_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int requestType = data.readInt();
+            Bundle res = getTopActivityExtras(requestType);
+            reply.writeNoException();
+            reply.writeBundle(res);
+            return true;
+        }
+
+        case REPORT_TOP_ACTIVITY_EXTRAS_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder token = data.readStrongBinder();
+            Bundle extras = data.readBundle();
+            reportTopActivityExtras(token, extras);
+            reply.writeNoException();
+            return true;
+        }
+
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -4149,5 +4167,30 @@
         return res;
     }
 
+    public Bundle getTopActivityExtras(int requestType) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(requestType);
+        mRemote.transact(GET_TOP_ACTIVITY_EXTRAS_TRANSACTION, data, reply, 0);
+        reply.readException();
+        Bundle res = reply.readBundle();
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
+    public void reportTopActivityExtras(IBinder token, Bundle extras) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(token);
+        data.writeBundle(extras);
+        mRemote.transact(REPORT_TOP_ACTIVITY_EXTRAS_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1271645..570fb80 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -533,6 +533,12 @@
         String pkg;
         CompatibilityInfo info;
     }
+
+    static final class RequestActivityExtras {
+        IBinder activityToken;
+        IBinder requestToken;
+        int requestType;
+    }
     
     private native void dumpGraphicsInfo(FileDescriptor fd);
 
@@ -1108,6 +1114,16 @@
             queueOrSendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
         }
 
+        @Override
+        public void requestActivityExtras(IBinder activityToken, IBinder requestToken,
+                int requestType) {
+            RequestActivityExtras cmd = new RequestActivityExtras();
+            cmd.activityToken = activityToken;
+            cmd.requestToken = requestToken;
+            cmd.requestType = requestType;
+            queueOrSendMessage(H.REQUEST_ACTIVITY_EXTRAS, cmd);
+        }
+
         private void printRow(PrintWriter pw, String format, Object...objs) {
             pw.println(String.format(format, objs));
         }
@@ -1173,6 +1189,7 @@
         public static final int TRIM_MEMORY             = 140;
         public static final int DUMP_PROVIDER           = 141;
         public static final int UNSTABLE_PROVIDER_DIED  = 142;
+        public static final int REQUEST_ACTIVITY_EXTRAS = 143;
         String codeToString(int code) {
             if (DEBUG_MESSAGES) {
                 switch (code) {
@@ -1219,6 +1236,7 @@
                     case TRIM_MEMORY: return "TRIM_MEMORY";
                     case DUMP_PROVIDER: return "DUMP_PROVIDER";
                     case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
+                    case REQUEST_ACTIVITY_EXTRAS: return "REQUEST_ACTIVITY_EXTRAS";
                 }
             }
             return Integer.toString(code);
@@ -1430,6 +1448,9 @@
                 case UNSTABLE_PROVIDER_DIED:
                     handleUnstableProviderDied((IBinder)msg.obj, false);
                     break;
+                case REQUEST_ACTIVITY_EXTRAS:
+                    handleRequestActivityExtras((RequestActivityExtras)msg.obj);
+                    break;
             }
             if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
         }
@@ -2322,6 +2343,23 @@
         performNewIntents(data.token, data.intents);
     }
 
+    public void handleRequestActivityExtras(RequestActivityExtras cmd) {
+        Bundle data = new Bundle();
+        ActivityClientRecord r = mActivities.get(cmd.activityToken);
+        if (r != null) {
+            r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data);
+            r.activity.onProvideAssistData(data);
+        }
+        if (data.isEmpty()) {
+            data = null;
+        }
+        IActivityManager mgr = ActivityManagerNative.getDefault();
+        try {
+            mgr.reportTopActivityExtras(cmd.requestToken, data);
+        } catch (RemoteException e) {
+        }
+    }
+    
     private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
 
     /**
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 4cea6a0..b1d0305 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -44,19 +44,44 @@
     public static final int OP_WRITE_CONTACTS = 5;
     public static final int OP_READ_CALL_LOG = 6;
     public static final int OP_WRITE_CALL_LOG = 7;
+    public static final int OP_READ_CALENDAR = 8;
+    public static final int OP_WRITE_CALENDAR = 9;
+    public static final int OP_WIFI_SCAN = 10;
 
-    public static String opToString(int op) {
-        switch (op) {
-            case OP_COARSE_LOCATION: return "COARSE_LOCATION";
-            case OP_FINE_LOCATION: return "FINE_LOCATION";
-            case OP_GPS: return "GPS";
-            case OP_VIBRATE: return "VIBRATE";
-            case OP_READ_CONTACTS: return "READ_CONTACTS";
-            case OP_WRITE_CONTACTS: return "WRITE_CONTACTS";
-            case OP_READ_CALL_LOG: return "READ_CALL_LOG";
-            case OP_WRITE_CALL_LOG: return "WRITE_CALL_LOG";
-            default: return "Unknown(" + op + ")";
-        }
+    private static String[] sOpNames = new String[] {
+        "COARSE_LOCATION",
+        "FINE_LOCATION",
+        "GPS",
+        "VIBRATE",
+        "READ_CONTACTS",
+        "WRITE_CONTACTS",
+        "READ_CALL_LOG",
+        "WRITE_CALL_LOG",
+        "READ_CALENDAR",
+        "WRITE_CALENDAR",
+        "WIFI_SCAN",
+    };
+
+    private static String[] sOpPerms = new String[] {
+        android.Manifest.permission.ACCESS_COARSE_LOCATION,
+        android.Manifest.permission.ACCESS_FINE_LOCATION,
+        android.Manifest.permission.ACCESS_FINE_LOCATION,
+        android.Manifest.permission.VIBRATE,
+        android.Manifest.permission.READ_CONTACTS,
+        android.Manifest.permission.WRITE_CONTACTS,
+        android.Manifest.permission.READ_CALL_LOG,
+        android.Manifest.permission.WRITE_CALL_LOG,
+        android.Manifest.permission.READ_CALENDAR,
+        android.Manifest.permission.WRITE_CALENDAR,
+        android.Manifest.permission.ACCESS_WIFI_STATE,
+    };
+
+    public static String opToName(int op) {
+        return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")");
+    }
+
+    public static String opToPermission(int op) {
+        return sOpPerms[op];
     }
 
     public static class PackageOps implements Parcelable {
@@ -120,12 +145,16 @@
 
     public static class OpEntry implements Parcelable {
         private final int mOp;
+        private final int mMode;
         private final long mTime;
+        private final long mRejectTime;
         private final int mDuration;
 
-        public OpEntry(int op, long time, int duration) {
+        public OpEntry(int op, int mode, long time, long rejectTime, int duration) {
             mOp = op;
+            mMode = mode;
             mTime = time;
+            mRejectTime = rejectTime;
             mDuration = duration;
         }
 
@@ -133,10 +162,18 @@
             return mOp;
         }
 
+        public int getMode() {
+            return mMode;
+        }
+
         public long getTime() {
             return mTime;
         }
 
+        public long getRejectTime() {
+            return mRejectTime;
+        }
+
         public boolean isRunning() {
             return mDuration == -1;
         }
@@ -153,13 +190,17 @@
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(mOp);
+            dest.writeInt(mMode);
             dest.writeLong(mTime);
+            dest.writeLong(mRejectTime);
             dest.writeInt(mDuration);
         }
 
         OpEntry(Parcel source) {
             mOp = source.readInt();
+            mMode = source.readInt();
             mTime = source.readLong();
+            mRejectTime = source.readLong();
             mDuration = source.readInt();
         }
 
@@ -187,6 +228,21 @@
         return null;
     }
 
+    public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) {
+        try {
+            return mService.getOpsForPackage(uid, packageName, ops);
+        } catch (RemoteException e) {
+        }
+        return null;
+    }
+
+    public void setMode(int code, int uid, String packageName, int mode) {
+        try {
+            mService.setMode(code, uid, packageName, mode);
+        } catch (RemoteException e) {
+        }
+    }
+
     public int checkOp(int op, int uid, String packageName) {
         try {
             int mode = mService.checkOperation(op, uid, packageName);
@@ -228,7 +284,7 @@
     }
 
     public int noteOp(int op) {
-        return noteOp(op, Process.myUid(), mContext.getPackageName());
+        return noteOp(op, Process.myUid(), mContext.getBasePackageName());
     }
 
     public int startOp(int op, int uid, String packageName) {
@@ -252,7 +308,7 @@
     }
 
     public int startOp(int op) {
-        return startOp(op, Process.myUid(), mContext.getPackageName());
+        return startOp(op, Process.myUid(), mContext.getBasePackageName());
     }
 
     public void finishOp(int op, int uid, String packageName) {
@@ -263,6 +319,6 @@
     }
 
     public void finishOp(int op) {
-        finishOp(op, Process.myUid(), mContext.getPackageName());
+        finishOp(op, Process.myUid(), mContext.getBasePackageName());
     }
 }
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 3a67cec..132388e 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -22,6 +22,7 @@
 import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.ContextWrapper;
+import android.content.Intent;
 import android.content.res.Configuration;
 import android.os.Bundle;
 
@@ -45,6 +46,7 @@
             new ArrayList<ComponentCallbacks>();
     private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
             new ArrayList<ActivityLifecycleCallbacks>();
+    private ArrayList<OnProvideAssistData> mAssistCallbacks = null;
 
     /** @hide */
     public LoadedApk mLoadedApk;
@@ -59,6 +61,21 @@
         void onActivityDestroyed(Activity activity);
     }
 
+    /**
+     * Callback interface for use with {@link Application#registerOnProvideAssistData}
+     * and {@link Application#unregisterOnProvideAssistData}.
+     */
+    public interface OnProvideAssistData {
+        /**
+         * This is called when the user is requesting an assist, to build a full
+         * {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
+         * application.  You can override this method to place into the bundle anything
+         * you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
+         * of the assist Intent.
+         */
+        public void onProvideAssistData(Activity activity, Bundle data);
+    }
+
     public Application() {
         super(null);
     }
@@ -137,7 +154,24 @@
             mActivityLifecycleCallbacks.remove(callback);
         }
     }
-    
+
+    public void registerOnProvideAssistData(OnProvideAssistData callback) {
+        synchronized (this) {
+            if (mAssistCallbacks == null) {
+                mAssistCallbacks = new ArrayList<OnProvideAssistData>();
+            }
+            mAssistCallbacks.add(callback);
+        }
+    }
+
+    public void unregisterOnProvideAssistData(OnProvideAssistData callback) {
+        synchronized (this) {
+            if (mAssistCallbacks != null) {
+                mAssistCallbacks.remove(callback);
+            }
+        }
+    }
+
     // ------------------ Internal API ------------------
     
     /**
@@ -232,4 +266,19 @@
         }
         return callbacks;
     }
+
+    /* package */ void dispatchOnProvideAssistData(Activity activity, Bundle data) {
+        Object[] callbacks;
+        synchronized (this) {
+            if (mAssistCallbacks == null) {
+                return;
+            }
+            callbacks = mAssistCallbacks.toArray();
+        }
+        if (callbacks != null) {
+            for (int i=0; i<callbacks.length; i++) {
+                ((OnProvideAssistData)callbacks[i]).onProvideAssistData(activity, data);
+            }
+        }
+    }
 }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 2ef3944..f09c2fe 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -426,17 +426,8 @@
     @Override
     public List<PackageInfo> getInstalledPackages(int flags, int userId) {
         try {
-            final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
-            PackageInfo lastItem = null;
-            ParceledListSlice<PackageInfo> slice;
-
-            do {
-                final String lastKey = lastItem != null ? lastItem.packageName : null;
-                slice = mPM.getInstalledPackages(flags, lastKey, userId);
-                lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
-            } while (!slice.isLastSlice());
-
-            return packageInfos;
+            ParceledListSlice<PackageInfo> slice = mPM.getInstalledPackages(flags, userId);
+            return slice.getList();
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -448,17 +439,9 @@
             String[] permissions, int flags) {
         final int userId = mContext.getUserId();
         try {
-            final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
-            PackageInfo lastItem = null;
-            ParceledListSlice<PackageInfo> slice;
-
-            do {
-                final String lastKey = lastItem != null ? lastItem.packageName : null;
-                slice = mPM.getPackagesHoldingPermissions(permissions, flags, lastKey, userId);
-                lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
-            } while (!slice.isLastSlice());
-
-            return packageInfos;
+            ParceledListSlice<PackageInfo> slice = mPM.getPackagesHoldingPermissions(
+                    permissions, flags, userId);
+            return slice.getList();
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -469,17 +452,8 @@
     public List<ApplicationInfo> getInstalledApplications(int flags) {
         final int userId = mContext.getUserId();
         try {
-            final List<ApplicationInfo> applicationInfos = new ArrayList<ApplicationInfo>();
-            ApplicationInfo lastItem = null;
-            ParceledListSlice<ApplicationInfo> slice;
-
-            do {
-                final String lastKey = lastItem != null ? lastItem.packageName : null;
-                slice = mPM.getInstalledApplications(flags, lastKey, userId);
-                lastItem = slice.populateList(applicationInfos, ApplicationInfo.CREATOR);
-            } while (!slice.isLastSlice());
-
-            return applicationInfos;
+            ParceledListSlice<ApplicationInfo> slice = mPM.getInstalledApplications(flags, userId);
+            return slice.getList();
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 63aa5f9..f0e367c 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -587,6 +587,17 @@
             reply.writeNoException();
             return true;
         }
+
+        case REQUEST_ACTIVITY_EXTRAS_TRANSACTION:
+        {
+            data.enforceInterface(IApplicationThread.descriptor);
+            IBinder activityToken = data.readStrongBinder();
+            IBinder requestToken = data.readStrongBinder();
+            int requestType = data.readInt();
+            requestActivityExtras(activityToken, requestToken, requestType);
+            reply.writeNoException();
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -1185,4 +1196,15 @@
         mRemote.transact(UNSTABLE_PROVIDER_DIED_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
         data.recycle();
     }
+
+    public void requestActivityExtras(IBinder activityToken, IBinder requestToken, int requestType)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeStrongBinder(activityToken);
+        data.writeStrongBinder(requestToken);
+        data.writeInt(requestType);
+        mRemote.transact(REQUEST_ACTIVITY_EXTRAS_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+        data.recycle();
+    }
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 4925bf1..fd4389e 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -628,6 +628,12 @@
         return "android";
     }
 
+    /** @hide */
+    @Override
+    public String getBasePackageName() {
+        return mBasePackageName != null ? mBasePackageName : getPackageName();
+    }
+
     @Override
     public ApplicationInfo getApplicationInfo() {
         if (mPackageInfo != null) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 8af17a4..baac07f 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -368,6 +368,10 @@
 
     public long inputDispatchingTimedOut(int pid, boolean aboveSystem) throws RemoteException;
 
+    public Bundle getTopActivityExtras(int requestType) throws RemoteException;
+
+    public void reportTopActivityExtras(IBinder token, Bundle extras) throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -624,4 +628,6 @@
     int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158;
     int CLEAR_PENDING_BACKUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+159;
     int GET_INTENT_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+160;
+    int GET_TOP_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+161;
+    int REPORT_TOP_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+162;
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 03a26d4..8516694 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -130,6 +130,8 @@
     void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
     void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
     void unstableProviderDied(IBinder provider) throws RemoteException;
+    void requestActivityExtras(IBinder activityToken, IBinder requestToken, int requestType)
+            throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
 
@@ -179,4 +181,5 @@
     int DUMP_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+44;
     int DUMP_DB_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+45;
     int UNSTABLE_PROVIDER_DIED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+46;
+    int REQUEST_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+47;
 }
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index e0856ae..39186c6 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -27,6 +27,7 @@
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.MessageQueue;
 import android.os.PerformanceCollector;
 import android.os.Process;
@@ -1637,7 +1638,7 @@
     }
     
     private final void validateNotAppThread() {
-        if (ActivityThread.currentActivityThread() != null) {
+        if (Looper.myLooper() == Looper.getMainLooper()) {
             throw new RuntimeException(
                 "This method can not be called from the main application thread");
         }
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 6382cee..7dfc589f 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -846,8 +846,8 @@
      *
      * @hide
      */
-    public Intent getAssistIntent(Context context) {
-        return getAssistIntent(context, UserHandle.myUserId());
+    public Intent getAssistIntent(Context context, boolean inclContext) {
+        return getAssistIntent(context, inclContext, UserHandle.myUserId());
     }
 
     /**
@@ -856,7 +856,7 @@
      *
      * @hide
      */
-    public Intent getAssistIntent(Context context, int userHandle) {
+    public Intent getAssistIntent(Context context, boolean inclContext, int userHandle) {
         try {
             if (mService == null) {
                 return null;
@@ -867,6 +867,13 @@
             }
             Intent intent = new Intent(Intent.ACTION_ASSIST);
             intent.setComponent(comp);
+            if (inclContext) {
+                IActivityManager am = ActivityManagerNative.getDefault();
+                Bundle extras = am.getTopActivityExtras(0);
+                if (extras != null) {
+                    intent.replaceExtras(extras);
+                }
+            }
             return intent;
         } catch (RemoteException re) {
             Log.e(TAG, "getAssistIntent() failed: " + re);
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index a6f7abc..4b977ab 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -190,8 +190,13 @@
         public Cursor query(String callingPkg, Uri uri, String[] projection,
                 String selection, String[] selectionArgs, String sortOrder,
                 ICancellationSignal cancellationSignal) {
-            // XXX need content provider to help return correct result.
-            enforceReadPermission(callingPkg, uri);
+            if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+                // The read is not allowed...  to fake it out, we replace the given
+                // selection statement with a dummy one that will always be false.
+                // This way we will get a cursor back that has the correct structure
+                // but contains no rows.
+                selection = "'A' = 'B'";
+            }
             return ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder,
                     CancellationSignal.fromTransport(cancellationSignal));
         }
@@ -203,8 +208,14 @@
 
         @Override
         public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
-            // XXX need content provider to help return correct result.
-            enforceWritePermission(callingPkg, uri);
+            if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+                // If not allowed, we need to return some reasonable URI.  Maybe the
+                // content provider should be responsible for this, but for now we
+                // will just return the base URI with a dummy '0' tagged on to it.
+                // You shouldn't be able to read if you can't write, anyway, so it
+                // shouldn't matter much what is returned.
+                return uri.buildUpon().appendPath("0").build();
+            }
             return ContentProvider.this.insert(uri, initialValues);
         }
 
@@ -1189,12 +1200,10 @@
      * Print the Provider's state into the given stream.  This gets invoked if
      * you run "adb shell dumpsys activity provider &lt;provider_component_name&gt;".
      *
-     * @param prefix Desired prefix to prepend at each line of output.
      * @param fd The raw file descriptor that the dump is being sent to.
      * @param writer The PrintWriter to which you should dump your state.  This will be
      * closed for you after you return.
      * @param args additional arguments to the dump request.
-     * @hide
      */
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         writer.println("nothing to dump");
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index fb73529..63c97ba 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -208,7 +208,7 @@
 
     public ContentResolver(Context context) {
         mContext = context != null ? context : ActivityThread.currentApplication();
-        mPackageName = mContext.getPackageName();
+        mPackageName = context.getBasePackageName();
     }
 
     /** @hide */
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 14f2847..f7c28b6 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -418,6 +418,9 @@
     /** Return the name of this application's package. */
     public abstract String getPackageName();
 
+    /** @hide Return the name of the base context this context is derived from. */
+    public abstract String getBasePackageName();
+
     /** Return the full application info for this context's package. */
     public abstract ApplicationInfo getApplicationInfo();
 
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 6a61884..b63f45e 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -135,6 +135,12 @@
         return mBase.getPackageName();
     }
 
+    /** @hide */
+    @Override
+    public String getBasePackageName() {
+        return mBase.getBasePackageName();
+    }
+
     @Override
     public ApplicationInfo getApplicationInfo() {
         return mBase.getApplicationInfo();
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 89b1bbd..dc367dd 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1140,14 +1140,33 @@
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
+
     /**
      * Activity Action: Perform assist action.
      * <p>
-     * Input: nothing
+     * Input: {@link #EXTRA_ASSIST_PACKAGE} and {@link #EXTRA_ASSIST_CONTEXT} can provide
+     * additional optional contextual information about where the user was when they requested
+     * the assist.
      * Output: nothing.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_ASSIST = "android.intent.action.ASSIST";
+
+    /**
+     * An optional field on {@link #ACTION_ASSIST} containing the name of the current
+     * foreground application package at the time the assist was invoked.
+     */
+    public static final String EXTRA_ASSIST_PACKAGE
+            = "android.intent.extra.ASSIST_PACKAGE";
+
+    /**
+     * An optional field on {@link #ACTION_ASSIST} containing additional contextual
+     * information supplied by the current foreground app at the time of the assist
+     * request.  This is a {@link Bundle} of additional data.
+     */
+    public static final String EXTRA_ASSIST_CONTEXT
+            = "android.intent.extra.ASSIST_CONTEXT";
+
     /**
      * Activity Action: List all available applications
      * <p>Input: Nothing.
@@ -1588,7 +1607,7 @@
      * <ul>
      * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package.
      * <li> {@link #EXTRA_CHANGED_COMPONENT_NAME_LIST} containing the class name
-     * of the changed components.
+     * of the changed components (or the package name itself).
      * <li> {@link #EXTRA_DONT_KILL_APP} containing boolean field to override the
      * default action of restarting the application.
      * </ul>
@@ -2969,7 +2988,9 @@
 
     /**
      * This field is part of {@link android.content.Intent#ACTION_PACKAGE_CHANGED},
-     * and contains a string array of all of the components that have changed.
+     * and contains a string array of all of the components that have changed.  If
+     * the state of the overall package has changed, then it will contain an entry
+     * with the package name itself.
      */
     public static final String EXTRA_CHANGED_COMPONENT_NAME_LIST =
             "android.intent.extra.changed_component_name_list";
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 4c9c278..0445b39 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -127,7 +127,7 @@
      * limit that kicks in when flags are included that bloat up the data
      * returned.
      */
-    ParceledListSlice getInstalledPackages(int flags, in String lastRead, in int userId);
+    ParceledListSlice getInstalledPackages(int flags, in int userId);
 
     /**
      * This implements getPackagesHoldingPermissions via a "last returned row"
@@ -136,7 +136,7 @@
      * returned.
      */
     ParceledListSlice getPackagesHoldingPermissions(in String[] permissions,
-            int flags, in String lastRead, int userId);
+            int flags, int userId);
 
     /**
      * This implements getInstalledApplications via a "last returned row"
@@ -144,7 +144,7 @@
      * limit that kicks in when flags are included that bloat up the data
      * returned.
      */
-    ParceledListSlice getInstalledApplications(int flags, in String lastRead, int userId);
+    ParceledListSlice getInstalledApplications(int flags, int userId);
 
     /**
      * Retrieve all applications that are marked as persistent.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a69f220..d80598c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -175,6 +175,14 @@
     public static final int GET_CONFIGURATIONS = 0x00004000;
 
     /**
+     * {@link PackageInfo} flag: include disabled components which are in
+     * that state only because of {@link #COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED}
+     * in the returned info.  Note that if you set this flag, applications
+     * that are in this disabled state will be reported as enabled.
+     */
+    public static final int GET_DISABLED_UNTIL_USED_COMPONENTS = 0x00008000;
+
+    /**
      * Resolution and querying flag: if set, only filters that support the
      * {@link android.content.Intent#CATEGORY_DEFAULT} will be considered for
      * matching.  This is a synonym for including the CATEGORY_DEFAULT in your
@@ -265,6 +273,19 @@
     public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3;
 
     /**
+     * Flag for {@link #setApplicationEnabledSetting(String, int, int)} only: This
+     * application should be considered, until the point where the user actually
+     * wants to use it.  This means that it will not normally show up to the user
+     * (such as in the launcher), but various parts of the user interface can
+     * use {@link #GET_DISABLED_UNTIL_USED_COMPONENTS} to still see it and allow
+     * the user to select it (as for example an IME, device admin, etc).  Such code,
+     * once the user has selected the app, should at that point also make it enabled.
+     * This option currently <strong>can not</strong> be used with
+     * {@link #setComponentEnabledSetting(ComponentName, int, int)}.
+     */
+    public static final int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4;
+
+    /**
      * Flag parameter for {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} to
      * indicate that this package should be installed as forward locked, i.e. only the app itself
      * should have access to its code and non-resource assets.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 3e8c2a8..e1887bc 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3527,29 +3527,45 @@
         return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
     }
 
+    private static void updateApplicationInfo(ApplicationInfo ai, int flags,
+            PackageUserState state) {
+        // CompatibilityMode is global state.
+        if (!sCompatibilityModeEnabled) {
+            ai.disableCompatibilityMode();
+        }
+        if (state.installed) {
+            ai.flags |= ApplicationInfo.FLAG_INSTALLED;
+        } else {
+            ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
+        }
+        if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+            ai.enabled = true;
+        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+            ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
+        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+                || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
+            ai.enabled = false;
+        }
+        ai.enabledSetting = state.enabled;
+    }
+
     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
             PackageUserState state, int userId) {
         if (p == null) return null;
         if (!checkUseInstalled(flags, state)) {
             return null;
         }
-        if (!copyNeeded(flags, p, state, null, userId)) {
-            // CompatibilityMode is global state. It's safe to modify the instance
-            // of the package.
-            if (!sCompatibilityModeEnabled) {
-                p.applicationInfo.disableCompatibilityMode();
-            }
-            // Make sure we report as installed.  Also safe to do, since the
-            // default state should be installed (we will always copy if we
-            // need to report it is not installed).
-            p.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
-            if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
-                p.applicationInfo.enabled = true;
-            } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
-                    || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
-                p.applicationInfo.enabled = false;
-            }
-            p.applicationInfo.enabledSetting = state.enabled;
+        if (!copyNeeded(flags, p, state, null, userId)
+                && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
+                        || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
+            // In this case it is safe to directly modify the internal ApplicationInfo state:
+            // - CompatibilityMode is global state, so will be the same for every call.
+            // - We only come in to here if the app should reported as installed; this is the
+            // default state, and we will do a copy otherwise.
+            // - The enable state will always be reported the same for the application across
+            // calls; the only exception is for the UNTIL_USED mode, and in that case we will
+            // be doing a copy.
+            updateApplicationInfo(p.applicationInfo, flags, state);
             return p.applicationInfo;
         }
 
@@ -3565,26 +3581,12 @@
         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
             ai.sharedLibraryFiles = p.usesLibraryFiles;
         }
-        if (!sCompatibilityModeEnabled) {
-            ai.disableCompatibilityMode();
-        }
         if (state.stopped) {
             ai.flags |= ApplicationInfo.FLAG_STOPPED;
         } else {
             ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
         }
-        if (state.installed) {
-            ai.flags |= ApplicationInfo.FLAG_INSTALLED;
-        } else {
-            ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
-        }
-        if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
-            ai.enabled = true;
-        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
-                || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
-            ai.enabled = false;
-        }
-        ai.enabledSetting = state.enabled;
+        updateApplicationInfo(ai, flags, state);
         return ai;
     }
 
diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java
index f3a98db4..8a43472 100644
--- a/core/java/android/content/pm/ParceledListSlice.java
+++ b/core/java/android/content/pm/ParceledListSlice.java
@@ -16,44 +16,92 @@
 
 package android.content.pm;
 
+import android.os.Binder;
+import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.RemoteException;
+import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Builds up a parcel that is discarded when written to another parcel or
- * written to a list. This is useful for API that sends huge lists across a
- * Binder that may be larger than the IPC limit.
+ * Transfer a large list of Parcelable objects across an IPC.  Splits into
+ * multiple transactions if needed.
  *
  * @hide
  */
 public class ParceledListSlice<T extends Parcelable> implements Parcelable {
+    private static String TAG = "ParceledListSlice";
+    private static boolean DEBUG = false;
+
     /*
      * TODO get this number from somewhere else. For now set it to a quarter of
      * the 1MB limit.
      */
     private static final int MAX_IPC_SIZE = 256 * 1024;
+    private static final int MAX_FIRST_IPC_SIZE = MAX_IPC_SIZE / 2;
 
-    private Parcel mParcel;
+    private final List<T> mList;
 
-    private int mNumItems;
-
-    private boolean mIsLastSlice;
-
-    public ParceledListSlice() {
-        mParcel = Parcel.obtain();
+    public ParceledListSlice(List<T> list) {
+        mList = list;
     }
 
-    private ParceledListSlice(Parcel p, int numItems, boolean lastSlice) {
-        mParcel = p;
-        mNumItems = numItems;
-        mIsLastSlice = lastSlice;
+    private ParceledListSlice(Parcel p, ClassLoader loader) {
+        final int N = p.readInt();
+        mList = new ArrayList<T>(N);
+        if (DEBUG) Log.d(TAG, "Retrieving " + N + " items");
+        if (N <= 0) {
+            return;
+        }
+        Parcelable.Creator<T> creator = p.readParcelableCreator(loader);
+        int i = 0;
+        while (i < N) {
+            if (p.readInt() == 0) {
+                break;
+            }
+            mList.add(p.readCreator(creator, loader));
+            if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1));
+            i++;
+        }
+        if (i >= N) {
+            return;
+        }
+        final IBinder retriever = p.readStrongBinder();
+        while (i < N) {
+            if (DEBUG) Log.d(TAG, "Reading more @" + i + " of " + N + ": retriever=" + retriever);
+            Parcel data = Parcel.obtain();
+            Parcel reply = Parcel.obtain();
+            data.writeInt(i);
+            try {
+                retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failure retrieving array; only received " + i + " of " + N, e);
+                return;
+            }
+            while (i < N && reply.readInt() != 0) {
+                mList.add(reply.readCreator(creator, loader));
+                if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1));
+                i++;
+            }
+            reply.recycle();
+            data.recycle();
+        }
+    }
+
+    public List<T> getList() {
+        return mList;
     }
 
     @Override
     public int describeContents() {
-        return 0;
+        int contents = 0;
+        for (int i=0; i<mList.size(); i++) {
+            contents |= mList.get(i).describeContents();
+        }
+        return contents;
     }
 
     /**
@@ -63,104 +111,59 @@
      */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mNumItems);
-        dest.writeInt(mIsLastSlice ? 1 : 0);
-
-        if (mNumItems > 0) {
-            final int parcelSize = mParcel.dataSize();
-            dest.writeInt(parcelSize);
-            dest.appendFrom(mParcel, 0, parcelSize);
+        final int N = mList.size();
+        final int callFlags = flags;
+        dest.writeInt(N);
+        if (DEBUG) Log.d(TAG, "Writing " + N + " items");
+        if (N > 0) {
+            dest.writeParcelableCreator(mList.get(0));
+            int i = 0;
+            while (i < N && dest.dataSize() < MAX_FIRST_IPC_SIZE) {
+                dest.writeInt(1);
+                mList.get(i).writeToParcel(dest, callFlags);
+                if (DEBUG) Log.d(TAG, "Wrote inline #" + i + ": " + mList.get(i));
+                i++;
+            }
+            if (i < N) {
+                dest.writeInt(0);
+                Binder retriever = new Binder() {
+                    @Override
+                    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+                            throws RemoteException {
+                        if (code != FIRST_CALL_TRANSACTION) {
+                            return super.onTransact(code, data, reply, flags);
+                        }
+                        int i = data.readInt();
+                        if (DEBUG) Log.d(TAG, "Writing more @" + i + " of " + N);
+                        while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
+                            reply.writeInt(1);
+                            mList.get(i).writeToParcel(reply, callFlags);
+                            if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i));
+                            i++;
+                        }
+                        if (i < N) {
+                            if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N);
+                            reply.writeInt(0);
+                        }
+                        return true;
+                    }
+                };
+                if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N + ": retriever=" + retriever);
+                dest.writeStrongBinder(retriever);
+            }
         }
-
-        mNumItems = 0;
-        mParcel.recycle();
-        mParcel = null;
-    }
-
-    /**
-     * Appends a parcel to this list slice.
-     *
-     * @param item Parcelable item to append to this list slice
-     * @return true when the list slice is full and should not be appended to
-     *         anymore
-     */
-    public boolean append(T item) {
-        if (mParcel == null) {
-            throw new IllegalStateException("ParceledListSlice has already been recycled");
-        }
-
-        item.writeToParcel(mParcel, PARCELABLE_WRITE_RETURN_VALUE);
-        mNumItems++;
-
-        return mParcel.dataSize() > MAX_IPC_SIZE;
-    }
-
-    /**
-     * Populates a list and discards the internal state of the
-     * ParceledListSlice in the process. The instance should
-     * not be used anymore.
-     *
-     * @param list list to insert items from this slice.
-     * @param creator creator that knows how to unparcel the
-     *        target object type.
-     * @return the last item inserted into the list or null if none.
-     */
-    public T populateList(List<T> list, Creator<T> creator) {
-        mParcel.setDataPosition(0);
-
-        T item = null;
-        for (int i = 0; i < mNumItems; i++) {
-            item = creator.createFromParcel(mParcel);
-            list.add(item);
-        }
-
-        mParcel.recycle();
-        mParcel = null;
-
-        return item;
-    }
-
-    /**
-     * Sets whether this is the last list slice in the series.
-     *
-     * @param lastSlice
-     */
-    public void setLastSlice(boolean lastSlice) {
-        mIsLastSlice = lastSlice;
-    }
-
-    /**
-     * Returns whether this is the last slice in a series of slices.
-     *
-     * @return true if this is the last slice in the series.
-     */
-    public boolean isLastSlice() {
-        return mIsLastSlice;
     }
 
     @SuppressWarnings("unchecked")
-    public static final Parcelable.Creator<ParceledListSlice> CREATOR =
-            new Parcelable.Creator<ParceledListSlice>() {
+    public static final Parcelable.ClassLoaderCreator<ParceledListSlice> CREATOR =
+            new Parcelable.ClassLoaderCreator<ParceledListSlice>() {
         public ParceledListSlice createFromParcel(Parcel in) {
-            final int numItems = in.readInt();
-            final boolean lastSlice = in.readInt() == 1;
+            return new ParceledListSlice(in, null);
+        }
 
-            if (numItems > 0) {
-                final int parcelSize = in.readInt();
-
-                // Advance within this Parcel
-                int offset = in.dataPosition();
-                in.setDataPosition(offset + parcelSize);
-
-                Parcel p = Parcel.obtain();
-                p.setDataPosition(0);
-                p.appendFrom(in, offset, parcelSize);
-                p.setDataPosition(0);
-
-                return new ParceledListSlice(p, numItems, lastSlice);
-            } else {
-                return new ParceledListSlice();
-            }
+        @Override
+        public ParceledListSlice createFromParcel(Parcel in, ClassLoader loader) {
+            return new ParceledListSlice(in, loader);
         }
 
         public ParceledListSlice[] newArray(int size) {
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 846443d..c0a894b 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -24,6 +24,7 @@
 import java.net.SocketException;
 import java.security.KeyManagementException;
 import java.security.cert.X509Certificate;
+import java.security.interfaces.ECPrivateKey;
 import javax.net.SocketFactory;
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
@@ -88,6 +89,7 @@
     private TrustManager[] mTrustManagers = null;
     private KeyManager[] mKeyManagers = null;
     private byte[] mNpnProtocols = null;
+    private ECPrivateKey mChannelIdPrivateKey = null;
 
     private final int mHandshakeTimeoutMillis;
     private final SSLClientSessionCache mSessionCache;
@@ -319,6 +321,20 @@
     }
 
     /**
+     * Sets the {@link ECPrivateKey} to be used for TLS Channel ID by connections made by this
+     * factory.
+     *
+     * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables
+     *        TLS Channel ID). The private key has to be an Elliptic Curve (EC) key based on the
+     *        NIST P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1).
+     *
+     * @hide
+     */
+    public void setChannelIdPrivateKey(ECPrivateKey privateKey) {
+        mChannelIdPrivateKey = privateKey;
+    }
+
+    /**
      * Enables <a href="http://tools.ietf.org/html/rfc5077#section-3.2">session ticket</a>
      * support on the given socket.
      *
@@ -378,6 +394,7 @@
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(k, host, port, close);
         s.setNpnProtocols(mNpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         if (mSecure) {
             verifyHostname(s, host);
         }
@@ -397,6 +414,7 @@
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket();
         s.setNpnProtocols(mNpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         return s;
     }
 
@@ -414,6 +432,7 @@
                 addr, port, localAddr, localPort);
         s.setNpnProtocols(mNpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         return s;
     }
 
@@ -429,6 +448,7 @@
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(addr, port);
         s.setNpnProtocols(mNpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         return s;
     }
 
@@ -445,6 +465,7 @@
                 host, port, localAddr, localPort);
         s.setNpnProtocols(mNpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         if (mSecure) {
             verifyHostname(s, host);
         }
@@ -462,6 +483,7 @@
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(host, port);
         s.setNpnProtocols(mNpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         if (mSecure) {
             verifyHostname(s, host);
         }
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 1044931..d0e5019 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -352,14 +352,4 @@
     void setFirewallEgressSourceRule(String addr, boolean allow);
     void setFirewallEgressDestRule(String addr, int port, boolean allow);
     void setFirewallUidRule(int uid, boolean allow);
-
-    /**
-     * Set a process (pid) to use the name servers associated with the specified interface.
-     */
-    void setDnsIfaceForPid(String iface, int pid);
-
-    /**
-     * Clear a process (pid) from being associated with an interface.
-     */
-    void clearDnsIfaceForPid(int pid);
 }
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index d69fef0..31d323b 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1254,6 +1254,12 @@
         p.writeToParcel(this, parcelableFlags);
     }
 
+    /** @hide */
+    public final void writeParcelableCreator(Parcelable p) {
+        String name = p.getClass().getName();
+        writeString(name);
+    }
+
     /**
      * Write a generic serializable object in to a Parcel.  It is strongly
      * recommended that this method be avoided, since the serialization
@@ -2046,6 +2052,28 @@
      * was an error trying to instantiate the Parcelable.
      */
     public final <T extends Parcelable> T readParcelable(ClassLoader loader) {
+        Parcelable.Creator<T> creator = readParcelableCreator(loader);
+        if (creator == null) {
+            return null;
+        }
+        if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
+            return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
+        }
+        return creator.createFromParcel(this);
+    }
+
+    /** @hide */
+    public final <T extends Parcelable> T readCreator(Parcelable.Creator<T> creator,
+            ClassLoader loader) {
+        if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
+            return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
+        }
+        return creator.createFromParcel(this);
+    }
+
+    /** @hide */
+    public final <T extends Parcelable> Parcelable.Creator<T> readParcelableCreator(
+            ClassLoader loader) {
         String name = readString();
         if (name == null) {
             return null;
@@ -2101,10 +2129,7 @@
             }
         }
 
-        if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
-            return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
-        }
-        return creator.createFromParcel(this);
+        return creator;
     }
 
     /**
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 54ea385..08eba4f 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -38,7 +38,7 @@
     }
 
     public SystemVibrator(Context context) {
-        mPackageName = context.getPackageName();
+        mPackageName = context.getBasePackageName();
         mService = IVibratorService.Stub.asInterface(
                 ServiceManager.getService("vibrator"));
     }
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 69118fe..b79bdee 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -11,7 +11,7 @@
  */
 public class WorkSource implements Parcelable {
     static final String TAG = "WorkSource";
-    static final boolean DEBUG = true;
+    static final boolean DEBUG = false;
 
     int mNum;
     int[] mUids;
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 30a8626..f52b5e3 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -479,6 +479,7 @@
     }
 
     private final Context mContext;
+    private Connection mConnectingServiceConnection;
     private Connection mServiceConnection;
     private OnInitListener mInitListener;
     // Written from an unspecified application thread, read from
@@ -554,21 +555,24 @@
         initTts();
     }
 
-    private <R> R runActionNoReconnect(Action<R> action, R errorResult, String method) {
-        return runAction(action, errorResult, method, false);
+    private <R> R runActionNoReconnect(Action<R> action, R errorResult, String method,
+            boolean onlyEstablishedConnection) {
+        return runAction(action, errorResult, method, false, onlyEstablishedConnection);
     }
 
     private <R> R runAction(Action<R> action, R errorResult, String method) {
-        return runAction(action, errorResult, method, true);
+        return runAction(action, errorResult, method, true, true);
     }
 
-    private <R> R runAction(Action<R> action, R errorResult, String method, boolean reconnect) {
+    private <R> R runAction(Action<R> action, R errorResult, String method,
+            boolean reconnect, boolean onlyEstablishedConnection) {
         synchronized (mStartLock) {
             if (mServiceConnection == null) {
                 Log.w(TAG, method + " failed: not bound to TTS engine");
                 return errorResult;
             }
-            return mServiceConnection.runAction(action, errorResult, method, reconnect);
+            return mServiceConnection.runAction(action, errorResult, method, reconnect,
+                    onlyEstablishedConnection);
         }
     }
 
@@ -631,6 +635,7 @@
             return false;
         } else {
             Log.i(TAG, "Sucessfully bound to " + engine);
+            mConnectingServiceConnection = connection;
             return true;
         }
     }
@@ -654,6 +659,16 @@
      * so the TextToSpeech engine can be cleanly stopped.
      */
     public void shutdown() {
+        // Special case, we are asked to shutdown connection that did finalize its connection.
+        synchronized (mStartLock) {
+            if (mConnectingServiceConnection != null) {
+                mContext.unbindService(mConnectingServiceConnection);
+                mConnectingServiceConnection = null;
+                return;
+            }
+        }
+
+        // Post connection case
         runActionNoReconnect(new Action<Void>() {
             @Override
             public Void run(ITextToSpeechService service) throws RemoteException {
@@ -671,7 +686,7 @@
                 mCurrentEngine = null;
                 return null;
             }
-        }, null, "shutdown");
+        }, null, "shutdown", false);
     }
 
     /**
@@ -1310,7 +1325,9 @@
     private class Connection implements ServiceConnection {
         private ITextToSpeechService mService;
 
-        private OnServiceConnectedAsyncTask mOnServiceConnectedAsyncTask;
+        private SetupConnectionAsyncTask mOnSetupConnectionAsyncTask;
+
+        private boolean mEstablished;
 
         private final ITextToSpeechCallback.Stub mCallback = new ITextToSpeechCallback.Stub() {
             @Override
@@ -1338,13 +1355,11 @@
             }
         };
 
-        private class OnServiceConnectedAsyncTask extends AsyncTask<Void, Void, Integer> {
+        private class SetupConnectionAsyncTask extends AsyncTask<Void, Void, Integer> {
             private final ComponentName mName;
-            private final ITextToSpeechService mConnectedService;
 
-            public OnServiceConnectedAsyncTask(ComponentName name, IBinder service) {
+            public SetupConnectionAsyncTask(ComponentName name) {
                 mName = name;
-                mConnectedService = ITextToSpeechService.Stub.asInterface(service);
             }
 
             @Override
@@ -1355,8 +1370,8 @@
                     }
 
                     try {
-                        mConnectedService.setCallback(getCallerIdentity(), mCallback);
-                        String[] defaultLanguage = mConnectedService.getClientDefaultLanguage();
+                        mService.setCallback(getCallerIdentity(), mCallback);
+                        String[] defaultLanguage = mService.getClientDefaultLanguage();
 
                         mParams.putString(Engine.KEY_PARAM_LANGUAGE, defaultLanguage[0]);
                         mParams.putString(Engine.KEY_PARAM_COUNTRY, defaultLanguage[1]);
@@ -1374,13 +1389,10 @@
             @Override
             protected void onPostExecute(Integer result) {
                 synchronized(mStartLock) {
-                    if (mOnServiceConnectedAsyncTask == this) {
-                        mOnServiceConnectedAsyncTask = null;
+                    if (mOnSetupConnectionAsyncTask == this) {
+                        mOnSetupConnectionAsyncTask = null;
                     }
-
-                    mServiceConnection = Connection.this;
-                    mService = mConnectedService;
-
+                    mEstablished = true;
                     dispatchOnInit(result);
                 }
             }
@@ -1389,14 +1401,20 @@
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             synchronized(mStartLock) {
+                mConnectingServiceConnection = null;
+
                 Log.i(TAG, "Connected to " + name);
 
-                if (mOnServiceConnectedAsyncTask != null) {
-                    mOnServiceConnectedAsyncTask.cancel(false);
+                if (mOnSetupConnectionAsyncTask != null) {
+                    mOnSetupConnectionAsyncTask.cancel(false);
                 }
 
-                mOnServiceConnectedAsyncTask = new OnServiceConnectedAsyncTask(name, service);
-                mOnServiceConnectedAsyncTask.execute();
+                mService = ITextToSpeechService.Stub.asInterface(service);
+                mServiceConnection = Connection.this;
+
+                mEstablished = false;
+                mOnSetupConnectionAsyncTask = new SetupConnectionAsyncTask(name);
+                mOnSetupConnectionAsyncTask.execute();
             }
         }
 
@@ -1407,14 +1425,14 @@
         /**
          * Clear connection related fields and cancel mOnServiceConnectedAsyncTask if set.
          *
-         * @return true if we cancel mOnServiceConnectedAsyncTask in progress.
+         * @return true if we cancel mOnSetupConnectionAsyncTask in progress.
          */
         private boolean clearServiceConnection() {
             synchronized(mStartLock) {
                 boolean result = false;
-                if (mOnServiceConnectedAsyncTask != null) {
-                    result = mOnServiceConnectedAsyncTask.cancel(false);
-                    mOnServiceConnectedAsyncTask = null;
+                if (mOnSetupConnectionAsyncTask != null) {
+                    result = mOnSetupConnectionAsyncTask.cancel(false);
+                    mOnSetupConnectionAsyncTask = null;
                 }
 
                 mService = null;
@@ -1445,13 +1463,22 @@
             clearServiceConnection();
         }
 
-        public <R> R runAction(Action<R> action, R errorResult, String method, boolean reconnect) {
+        public boolean isEstablished() {
+            return mService != null && mEstablished;
+        }
+
+        public <R> R runAction(Action<R> action, R errorResult, String method,
+                boolean reconnect, boolean onlyEstablishedConnection) {
             synchronized (mStartLock) {
                 try {
                     if (mService == null) {
                         Log.w(TAG, method + " failed: not connected to TTS engine");
                         return errorResult;
                     }
+                    if (onlyEstablishedConnection && !isEstablished()) {
+                        Log.w(TAG, method + " failed: TTS engine connection not fully set up");
+                        return errorResult;
+                    }
                     return action.run(mService);
                 } catch (RemoteException ex) {
                     Log.e(TAG, method + " failed", ex);
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
new file mode 100644
index 0000000..34b6126
--- /dev/null
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Arrays;
+
+/**
+ * Map of {@code long} to {@code long}. Unlike a normal array of longs, there
+ * can be gaps in the indices. It is intended to be more efficient than using a
+ * {@code HashMap}.
+ *
+ * @hide
+ */
+public class LongSparseLongArray implements Cloneable {
+    private long[] mKeys;
+    private long[] mValues;
+    private int mSize;
+
+    /**
+     * Creates a new SparseLongArray containing no mappings.
+     */
+    public LongSparseLongArray() {
+        this(10);
+    }
+
+    /**
+     * Creates a new SparseLongArray containing no mappings that will not
+     * require any additional memory allocation to store the specified
+     * number of mappings.
+     */
+    public LongSparseLongArray(int initialCapacity) {
+        initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
+
+        mKeys = new long[initialCapacity];
+        mValues = new long[initialCapacity];
+        mSize = 0;
+    }
+
+    @Override
+    public LongSparseLongArray clone() {
+        LongSparseLongArray clone = null;
+        try {
+            clone = (LongSparseLongArray) super.clone();
+            clone.mKeys = mKeys.clone();
+            clone.mValues = mValues.clone();
+        } catch (CloneNotSupportedException cnse) {
+            /* ignore */
+        }
+        return clone;
+    }
+
+    /**
+     * Gets the long mapped from the specified key, or <code>0</code>
+     * if no such mapping has been made.
+     */
+    public long get(long key) {
+        return get(key, 0);
+    }
+
+    /**
+     * Gets the long mapped from the specified key, or the specified value
+     * if no such mapping has been made.
+     */
+    public long get(long key, long valueIfKeyNotFound) {
+        int i = Arrays.binarySearch(mKeys, 0, mSize, key);
+
+        if (i < 0) {
+            return valueIfKeyNotFound;
+        } else {
+            return mValues[i];
+        }
+    }
+
+    /**
+     * Removes the mapping from the specified key, if there was any.
+     */
+    public void delete(long key) {
+        int i = Arrays.binarySearch(mKeys, 0, mSize, key);
+
+        if (i >= 0) {
+            removeAt(i);
+        }
+    }
+
+    /**
+     * Removes the mapping at the given index.
+     */
+    public void removeAt(int index) {
+        System.arraycopy(mKeys, index + 1, mKeys, index, mSize - (index + 1));
+        System.arraycopy(mValues, index + 1, mValues, index, mSize - (index + 1));
+        mSize--;
+    }
+
+    /**
+     * Adds a mapping from the specified key to the specified value,
+     * replacing the previous mapping from the specified key if there
+     * was one.
+     */
+    public void put(long key, long value) {
+        int i = Arrays.binarySearch(mKeys, 0, mSize, key);
+
+        if (i >= 0) {
+            mValues[i] = value;
+        } else {
+            i = ~i;
+
+            if (mSize >= mKeys.length) {
+                growKeyAndValueArrays(mSize + 1);
+            }
+
+            if (mSize - i != 0) {
+                System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
+                System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
+            }
+
+            mKeys[i] = key;
+            mValues[i] = value;
+            mSize++;
+        }
+    }
+
+    /**
+     * Returns the number of key-value mappings that this SparseIntArray
+     * currently stores.
+     */
+    public int size() {
+        return mSize;
+    }
+
+    /**
+     * Given an index in the range <code>0...size()-1</code>, returns
+     * the key from the <code>index</code>th key-value mapping that this
+     * SparseLongArray stores.
+     */
+    public long keyAt(int index) {
+        return mKeys[index];
+    }
+
+    /**
+     * Given an index in the range <code>0...size()-1</code>, returns
+     * the value from the <code>index</code>th key-value mapping that this
+     * SparseLongArray stores.
+     */
+    public long valueAt(int index) {
+        return mValues[index];
+    }
+
+    /**
+     * Returns the index for which {@link #keyAt} would return the
+     * specified key, or a negative number if the specified
+     * key is not mapped.
+     */
+    public int indexOfKey(long key) {
+        return Arrays.binarySearch(mKeys, 0, mSize, key);
+    }
+
+    /**
+     * Returns an index for which {@link #valueAt} would return the
+     * specified key, or a negative number if no keys map to the
+     * specified value.
+     * Beware that this is a linear search, unlike lookups by key,
+     * and that multiple keys can map to the same value and this will
+     * find only one of them.
+     */
+    public int indexOfValue(long value) {
+        for (int i = 0; i < mSize; i++)
+            if (mValues[i] == value)
+                return i;
+
+        return -1;
+    }
+
+    /**
+     * Removes all key-value mappings from this SparseIntArray.
+     */
+    public void clear() {
+        mSize = 0;
+    }
+
+    /**
+     * Puts a key/value pair into the array, optimizing for the case where
+     * the key is greater than all existing keys in the array.
+     */
+    public void append(long key, long value) {
+        if (mSize != 0 && key <= mKeys[mSize - 1]) {
+            put(key, value);
+            return;
+        }
+
+        int pos = mSize;
+        if (pos >= mKeys.length) {
+            growKeyAndValueArrays(pos + 1);
+        }
+
+        mKeys[pos] = key;
+        mValues[pos] = value;
+        mSize = pos + 1;
+    }
+
+    private void growKeyAndValueArrays(int minNeededSize) {
+        int n = ArrayUtils.idealLongArraySize(minNeededSize);
+
+        long[] nkeys = new long[n];
+        long[] nvalues = new long[n];
+
+        System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
+        System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
+
+        mKeys = nkeys;
+        mValues = nvalues;
+    }
+}
diff --git a/core/java/android/view/SimulatedTrackball.java b/core/java/android/view/SimulatedDpad.java
similarity index 83%
rename from core/java/android/view/SimulatedTrackball.java
rename to core/java/android/view/SimulatedDpad.java
index 4ab557a..1ee416c 100644
--- a/core/java/android/view/SimulatedTrackball.java
+++ b/core/java/android/view/SimulatedDpad.java
@@ -28,15 +28,15 @@
 import android.util.Log;
 
 /**
- * This class creates trackball events from touchpad events.
+ * This class creates DPAD events from touchpad events.
  * 
  * @see ViewRootImpl
  */
 
 //TODO: Make this class an internal class of ViewRootImpl.java
-class SimulatedTrackball {
+class SimulatedDpad {
 
-    private static final String TAG = "SimulatedTrackball";
+    private static final String TAG = "SimulatedDpad";
 
     // Maximum difference in milliseconds between the down and up of a touch
     // event for it to be considered a tap
@@ -97,7 +97,7 @@
     // How quickly the repeated events die off
     private float mFlickDecay;
 
-    public SimulatedTrackball(Context context) {
+    public SimulatedDpad(Context context) {
         mDistancePerTick = SystemProperties.getInt("persist.vr_dist_tick", 64);
         mDistancePerTickSquared = mDistancePerTick * mDistancePerTick;
         mMaxRepeatDelay = SystemProperties.getInt("persist.vr_repeat_delay", 300);
@@ -140,7 +140,11 @@
         }
     };
 
-    public void updateTrackballDirection(ViewRootImpl viewroot, MotionEvent event) {
+    public void updateTouchPad(ViewRootImpl viewroot, MotionEvent event,
+            boolean synthesizeNewKeys) {
+        if (!synthesizeNewKeys) {
+            mHandler.removeMessages(MSG_FLICK);
+        }
         // Store what time the touchpad event occurred
         final long time = SystemClock.uptimeMillis();
         switch (event.getAction()) {
@@ -159,8 +163,9 @@
                     mEdgeSwipePossible = true;
                 }
                 // Clear any flings
-                mHandler.removeMessages(MSG_FLICK);
-
+                if (synthesizeNewKeys) {
+                    mHandler.removeMessages(MSG_FLICK);
+                }
                 break;
             case MotionEvent.ACTION_MOVE:
                 // Determine whether the move is slop or an intentional move
@@ -177,7 +182,7 @@
 
                     Intent intent =
                             ((SearchManager)mContext.getSystemService(Context.SEARCH_SERVICE))
-                            .getAssistIntent(mContext, UserHandle.USER_CURRENT_OR_SELF);
+                            .getAssistIntent(mContext, false, UserHandle.USER_CURRENT_OR_SELF);
                     if (intent != null) {
                         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                         try {
@@ -226,12 +231,16 @@
                     while (dominantAxis * dominantAxis > mDistancePerTickSquared) {
                         repeatCount++;
                         dominantAxis -= sign * mDistancePerTick;
-                        viewroot.enqueueInputEvent(new KeyEvent(time, time,
-                                KeyEvent.ACTION_DOWN, key, 0, event.getMetaState(),
-                                event.getDeviceId(), 0, KeyEvent.FLAG_FALLBACK, event.getSource()));
-                        viewroot.enqueueInputEvent(new KeyEvent(time, time,
-                                KeyEvent.ACTION_UP, key, 0, event.getMetaState(),
-                                event.getDeviceId(), 0, KeyEvent.FLAG_FALLBACK, event.getSource()));
+                        if (synthesizeNewKeys) {
+                            viewroot.enqueueInputEvent(new KeyEvent(time, time,
+                                    KeyEvent.ACTION_DOWN, key, 0, event.getMetaState(),
+                                    event.getDeviceId(), 0, KeyEvent.FLAG_FALLBACK,
+                                    event.getSource()));
+                            viewroot.enqueueInputEvent(new KeyEvent(time, time,
+                                    KeyEvent.ACTION_UP, key, 0, event.getMetaState(),
+                                    event.getDeviceId(), 0, KeyEvent.FLAG_FALLBACK,
+                                    event.getSource()));
+                        }
                     }
                     // Save new axis values
                     mAccumulatedX = isXAxis ? dominantAxis : 0;
@@ -244,18 +253,16 @@
                 break;
             case MotionEvent.ACTION_UP:
                 if (time - mLastTouchPadStartTimeMs < MAX_TAP_TIME && mAlwaysInTapRegion) {
-                    // Trackball Down
-                    MotionEvent trackballEvent = MotionEvent.obtain(mLastTouchPadStartTimeMs, time,
-                            MotionEvent.ACTION_DOWN, 0, 0, 0, 0, event.getMetaState(),
-                            10f, 10f, event.getDeviceId(), 0);
-                    trackballEvent.setSource(InputDevice.SOURCE_TRACKBALL);
-                    viewroot.enqueueInputEvent(trackballEvent);
-                    // Trackball Release
-                    trackballEvent = MotionEvent.obtain(mLastTouchPadStartTimeMs, time,
-                            MotionEvent.ACTION_UP, 0, 0, 0, 0, event.getMetaState(),
-                            10f, 10f, event.getDeviceId(), 0);
-                    trackballEvent.setSource(InputDevice.SOURCE_TRACKBALL);
-                    viewroot.enqueueInputEvent(trackballEvent);
+                    if (synthesizeNewKeys) {
+                        viewroot.enqueueInputEvent(new KeyEvent(mLastTouchPadStartTimeMs, time,
+                                KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0,
+                                event.getMetaState(), event.getDeviceId(), 0,
+                                KeyEvent.FLAG_FALLBACK, event.getSource()));
+                        viewroot.enqueueInputEvent(new KeyEvent(mLastTouchPadStartTimeMs, time,
+                                KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0,
+                                event.getMetaState(), event.getDeviceId(), 0,
+                                KeyEvent.FLAG_FALLBACK, event.getSource()));
+                    }
                 } else {
                     float xMoveSquared = mLastMoveX * mLastMoveX;
                     float yMoveSquared = mLastMoveY * mLastMoveY;
@@ -267,10 +274,12 @@
                         mLastSource = event.getSource();
                         mLastMetaState = event.getMetaState();
 
-                        Message message = Message.obtain(mHandler, MSG_FLICK,
-                                mKeySendRateMs, mLastKeySent, viewroot);
-                        message.setAsynchronous(true);
-                        mHandler.sendMessageDelayed(message, mKeySendRateMs);
+                        if (synthesizeNewKeys) {
+                            Message message = Message.obtain(mHandler, MSG_FLICK,
+                                    mKeySendRateMs, mLastKeySent, viewroot);
+                            message.setAsynchronous(true);
+                            mHandler.sendMessageDelayed(message, mKeySendRateMs);
+                        }
                     }
                 }
                 mEdgeSwipePossible = false;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1ae69fea..3faac40 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -144,7 +144,7 @@
     final TrackballAxis mTrackballAxisX = new TrackballAxis();
     final TrackballAxis mTrackballAxisY = new TrackballAxis();
 
-    final SimulatedTrackball mSimulatedTrackball;
+    final SimulatedDpad mSimulatedDpad;
 
     int mLastJoystickXDirection;
     int mLastJoystickYDirection;
@@ -391,7 +391,7 @@
         PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mAttachInfo.mScreenOn = powerManager.isScreenOn();
         loadSystemProperties();
-        mSimulatedTrackball = new SimulatedTrackball(context);
+        mSimulatedDpad = new SimulatedDpad(context);
     }
 
     /**
@@ -3535,8 +3535,7 @@
             if (isJoystick) {
                 updateJoystickDirection(event, false);
             } else if (isTouchPad) {
-              //Convert TouchPad motion into a TrackBall event
-              mSimulatedTrackball.updateTrackballDirection(this, event);
+              mSimulatedDpad.updateTouchPad(this, event, false);
             }
             return EVENT_NOT_HANDLED;
         }
@@ -3546,8 +3545,7 @@
             if (isJoystick) {
                 updateJoystickDirection(event, false);
             } else if (isTouchPad) {
-              //Convert TouchPad motion into a TrackBall event
-              mSimulatedTrackball.updateTrackballDirection(this, event);
+              mSimulatedDpad.updateTouchPad(this, event, false);
             }
             return EVENT_HANDLED;
         }
@@ -3559,8 +3557,7 @@
             return EVENT_HANDLED;
         }
         if (isTouchPad) {
-            //Convert TouchPad motion into a TrackBall event
-            mSimulatedTrackball.updateTrackballDirection(this, event);
+            mSimulatedDpad.updateTouchPad(this, event, true);
             return EVENT_HANDLED;
         }
         return EVENT_NOT_HANDLED;
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 6fb8bdf..0b7e92f 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -56,8 +56,8 @@
 import java.util.Set;
 
 import org.apache.harmony.security.provider.cert.X509CertImpl;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPrivateKey;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLKeyHolder;
 
 class BrowserFrame extends Handler {
 
@@ -1127,13 +1127,10 @@
         if (table.IsAllowed(hostAndPort)) {
             // previously allowed
             PrivateKey pkey = table.PrivateKey(hostAndPort);
-            if (pkey instanceof OpenSSLRSAPrivateKey) {
+            if (pkey instanceof OpenSSLKeyHolder) {
+                OpenSSLKey sslKey = ((OpenSSLKeyHolder) pkey).getOpenSSLKey();
                 nativeSslClientCert(handle,
-                                    ((OpenSSLRSAPrivateKey)pkey).getPkeyContext(),
-                                    table.CertificateChain(hostAndPort));
-            } else if (pkey instanceof OpenSSLDSAPrivateKey) {
-                nativeSslClientCert(handle,
-                                    ((OpenSSLDSAPrivateKey)pkey).getPkeyContext(),
+                                    sslKey.getPkeyContext(),
                                     table.CertificateChain(hostAndPort));
             } else {
                 nativeSslClientCert(handle,
diff --git a/core/java/android/webkit/ClientCertRequestHandler.java b/core/java/android/webkit/ClientCertRequestHandler.java
index 6570a9b8..dac1510 100644
--- a/core/java/android/webkit/ClientCertRequestHandler.java
+++ b/core/java/android/webkit/ClientCertRequestHandler.java
@@ -21,8 +21,8 @@
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
 import org.apache.harmony.xnet.provider.jsse.NativeCrypto;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPrivateKey;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLKeyHolder;
 
 /**
  * ClientCertRequestHandler: class responsible for handling client
@@ -56,14 +56,11 @@
             byte[][] chainBytes = NativeCrypto.encodeCertificates(chain);
             mTable.Allow(mHostAndPort, privateKey, chainBytes);
 
-            if (privateKey instanceof OpenSSLRSAPrivateKey) {
-                setSslClientCertFromCtx(((OpenSSLRSAPrivateKey)privateKey).getPkeyContext(),
-                           chainBytes);
-            } else if (privateKey instanceof OpenSSLDSAPrivateKey) {
-                setSslClientCertFromCtx(((OpenSSLDSAPrivateKey)privateKey).getPkeyContext(),
-                           chainBytes);
+            if (privateKey instanceof OpenSSLKeyHolder) {
+                OpenSSLKey pkey = ((OpenSSLKeyHolder) privateKey).getOpenSSLKey();
+                setSslClientCertFromCtx(pkey.getPkeyContext(), chainBytes);
             } else {
-                setSslClientCertFromPKCS8(privateKey.getEncoded(),chainBytes);
+                setSslClientCertFromPKCS8(privateKey.getEncoded(), chainBytes);
             }
         } catch (CertificateEncodingException e) {
             post(new Runnable() {
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index 1a4ccfa..c68b450 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -33,12 +33,15 @@
 import android.widget.EditText;
 import android.widget.TextView;
 
-class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
-        View.OnClickListener {
+/**
+ * @hide
+ */
+public class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
+        View.OnClickListener, WebView.FindListener {
     private View mCustomView;
     private EditText mEditText;
     private TextView mMatches;
-    private WebViewClassic mWebView;
+    private WebView mWebView;
     private InputMethodManager mInput;
     private Resources mResources;
     private boolean mMatchesFound;
@@ -46,7 +49,7 @@
     private int mActiveMatchIndex;
     private ActionMode mActionMode;
 
-    FindActionModeCallback(Context context) {
+    public FindActionModeCallback(Context context) {
         mCustomView = LayoutInflater.from(context).inflate(
                 com.android.internal.R.layout.webview_find, null);
         mEditText = (EditText) mCustomView.findViewById(
@@ -61,7 +64,7 @@
         mResources = context.getResources();
     }
 
-    void finish() {
+    public void finish() {
         mActionMode.finish();
     }
 
@@ -69,7 +72,7 @@
      * Place text in the text field so it can be searched for.  Need to press
      * the find next or find previous button to find all of the matches.
      */
-    void setText(String text) {
+    public void setText(String text) {
         mEditText.setText(text);
         Spannable span = (Spannable) mEditText.getText();
         int length = span.length();
@@ -84,15 +87,23 @@
     }
 
     /*
-     * Set the WebView to search.  Must be non null, and set before calling
-     * startActionMode.
+     * Set the WebView to search.  Must be non null.
      */
-    void setWebView(WebViewClassic webView) {
+    public void setWebView(WebView webView) {
         if (null == webView) {
             throw new AssertionError("WebView supplied to "
                     + "FindActionModeCallback cannot be null");
         }
         mWebView = webView;
+        mWebView.setFindDialogFindListener(this);
+    }
+
+    @Override
+    public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
+            boolean isDoneCounting) {
+        if (isDoneCounting) {
+            updateMatchCount(activeMatchOrdinal, numberOfMatches, numberOfMatches == 0);
+        }
     }
 
     /*
@@ -121,7 +132,7 @@
     /*
      * Highlight all the instances of the string from mEditText in mWebView.
      */
-    void findAll() {
+    public void findAll() {
         if (mWebView == null) {
             throw new AssertionError(
                     "No WebView for FindActionModeCallback::findAll");
@@ -152,7 +163,7 @@
             mActiveMatchIndex = matchIndex;
             updateMatchesString();
         } else {
-            mMatches.setVisibility(View.INVISIBLE);
+            mMatches.setVisibility(View.GONE);
             mNumberOfMatches = 0;
         }
     }
@@ -208,7 +219,8 @@
     public void onDestroyActionMode(ActionMode mode) {
         mActionMode = null;
         mWebView.notifyFindDialogDismissed();
-        mInput.hideSoftInputFromWindow(mWebView.getWebView().getWindowToken(), 0);
+        mWebView.setFindDialogFindListener(null);
+        mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
     }
 
     @Override
@@ -222,7 +234,7 @@
             throw new AssertionError(
                     "No WebView for FindActionModeCallback::onActionItemClicked");
         }
-        mInput.hideSoftInputFromWindow(mWebView.getWebView().getWindowToken(), 0);
+        mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
         switch(item.getItemId()) {
             case com.android.internal.R.id.find_prev:
                 findNext(false);
diff --git a/core/java/android/webkit/ViewStateSerializer.java b/core/java/android/webkit/ViewStateSerializer.java
index 096d4cda..1d44b96 100644
--- a/core/java/android/webkit/ViewStateSerializer.java
+++ b/core/java/android/webkit/ViewStateSerializer.java
@@ -31,7 +31,8 @@
 
     private static final int WORKING_STREAM_STORAGE = 16 * 1024;
 
-    static final int VERSION = 1;
+    // VERSION = 1 was for pictures encoded using a previous copy of libskia
+    static final int VERSION = 2;
 
     static boolean serializeViewState(OutputStream stream, DrawData draw)
             throws IOException {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 1abea2b..5412400 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1329,7 +1329,8 @@
      */
     public void setFindListener(FindListener listener) {
         checkThread();
-        mProvider.setFindListener(listener);
+        setupFindListenerIfNeeded();
+        mFindListener.mUserFindListener = listener;
     }
 
     /**
@@ -1850,11 +1851,60 @@
     }
 
     //-------------------------------------------------------------------------
+    // Package-private internal stuff
+    //-------------------------------------------------------------------------
+
+    // Only used by android.webkit.FindActionModeCallback.
+    void setFindDialogFindListener(FindListener listener) {
+        checkThread();
+        setupFindListenerIfNeeded();
+        mFindListener.mFindDialogFindListener = listener;
+    }
+
+    // Only used by android.webkit.FindActionModeCallback.
+    void notifyFindDialogDismissed() {
+        checkThread();
+        mProvider.notifyFindDialogDismissed();
+    }
+
+    //-------------------------------------------------------------------------
     // Private internal stuff
     //-------------------------------------------------------------------------
 
     private WebViewProvider mProvider;
 
+    /**
+     * In addition to the FindListener that the user may set via the WebView.setFindListener
+     * API, FindActionModeCallback will register it's own FindListener. We keep them separate
+     * via this class so that that the two FindListeners can potentially exist at once.
+     */
+    private class FindListenerDistributor implements FindListener {
+        private FindListener mFindDialogFindListener;
+        private FindListener mUserFindListener;
+
+        @Override
+        public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
+                boolean isDoneCounting) {
+            if (mFindDialogFindListener != null) {
+                mFindDialogFindListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches,
+                        isDoneCounting);
+            }
+
+            if (mUserFindListener != null) {
+                mUserFindListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches,
+                        isDoneCounting);
+            }
+        }
+    }
+    private FindListenerDistributor mFindListener;
+
+    private void setupFindListenerIfNeeded() {
+        if (mFindListener == null) {
+            mFindListener = new FindListenerDistributor();
+            mProvider.setFindListener(mFindListener);
+        }
+    }
+
     private void ensureProviderCreated() {
         checkThread();
         if (mProvider == null) {
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 9a83964..a867d39 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -3668,7 +3668,7 @@
         mCachedOverlappingActionModeHeight = -1;
         mFindCallback = callback;
         setFindIsUp(true);
-        mFindCallback.setWebView(this);
+        mFindCallback.setWebView(getWebView());
         if (showIme) {
             mFindCallback.showSoftInput();
         } else if (text != null) {
@@ -3770,7 +3770,8 @@
     /**
      * Called when the find ActionMode ends.
      */
-    void notifyFindDialogDismissed() {
+    @Override
+    public void notifyFindDialogDismissed() {
         mFindCallback = null;
         mCachedOverlappingActionModeHeight = -1;
         if (mWebViewCore == null) {
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 1020634..fa17ab9 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -240,7 +240,7 @@
     public View findHierarchyView(String className, int hashCode);
 
     //-------------------------------------------------------------------------
-    // Provider glue methods
+    // Provider internal methods
     //-------------------------------------------------------------------------
 
     /**
@@ -255,6 +255,12 @@
      */
     /* package */ ScrollDelegate getScrollDelegate();
 
+    /**
+     * Only used by FindActionModeCallback to inform providers that the find dialog has
+     * been dismissed.
+     */
+    public void notifyFindDialogDismissed();
+
     //-------------------------------------------------------------------------
     // View / ViewGroup delegation methods
     //-------------------------------------------------------------------------
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index e749e63..2b7e162 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -444,21 +444,14 @@
         // We need to know our size for doing the correct computation of positioning in RTL mode
         if (isLayoutRtl() && (myWidth == -1 || isWrapContentWidth)) {
             int w = getPaddingStart() + getPaddingEnd();
-            final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
             for (int i = 0; i < count; i++) {
                 View child = views[i];
                 if (child.getVisibility() != GONE) {
                     LayoutParams params = (LayoutParams) child.getLayoutParams();
-                    // Would be similar to a call to measureChildHorizontal(child, params, -1, myHeight)
-                    // but we cannot change for now the behavior of measureChildHorizontal() for
-                    // taking care or a "-1" for "mywidth" so use here our own version of that code.
-                    int childHeightMeasureSpec;
-                    if (params.width == LayoutParams.MATCH_PARENT) {
-                        childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.EXACTLY);
-                    } else {
-                        childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.AT_MOST);
-                    }
-                    child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+                    int[] rules = params.getRules(View.LAYOUT_DIRECTION_LTR);
+
+                    applyHorizontalSizeRules(params, myWidth, rules);
+                    measureChildHorizontal(child, params, -1, myHeight);
 
                     w += child.getMeasuredWidth();
                     w += params.leftMargin + params.rightMargin;
@@ -476,13 +469,16 @@
             }
         }
 
+        final int layoutDirection = getLayoutDirection();
         for (int i = 0; i < count; i++) {
             View child = views[i];
             if (child.getVisibility() != GONE) {
                 LayoutParams params = (LayoutParams) child.getLayoutParams();
+                int[] rules = params.getRules(layoutDirection);
 
-                applyHorizontalSizeRules(params, myWidth);
+                applyHorizontalSizeRules(params, myWidth, rules);
                 measureChildHorizontal(child, params, myWidth, myHeight);
+
                 if (positionChildHorizontal(child, params, myWidth, isWrapContentWidth)) {
                     offsetHorizontalAxis = true;
                 }
@@ -543,8 +539,6 @@
             }
         }
 
-        final int layoutDirection = getLayoutDirection();
-
         if (isWrapContentWidth) {
             // Width already has left padding in it since it was calculated by looking at
             // the right of each child view
@@ -862,9 +856,7 @@
         return rules[ALIGN_PARENT_BOTTOM] != 0;
     }
 
-    private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth) {
-        final int layoutDirection = getLayoutDirection();
-        int[] rules = childParams.getRules(layoutDirection);
+    private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth, int[] rules) {
         RelativeLayout.LayoutParams anchorParams;
 
         // -1 indicated a "soft requirement" in that direction. For example:
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 46478ca..f041f07 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -801,6 +801,11 @@
         return mThemedContext;
     }
     
+    @Override
+    public boolean isTitleTruncated() {
+        return mActionView != null && mActionView.isTitleTruncated();
+    }
+
     /**
      * @hide 
      */
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 827dba6..c4f1bc48 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -20,6 +20,8 @@
 
 interface IAppOpsService {
     List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops);
+    List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops);
+    void setMode(int code, int uid, String packageName, int mode);
     int checkOperation(int code, int uid, String packageName);
     int noteOperation(int code, int uid, String packageName);
     int startOperation(int code, int uid, String packageName);
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index 20ecace..424c19b 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -153,8 +153,33 @@
 
     public void onPackageUpdateFinished(String packageName, int uid) {
     }
-    
-    public void onPackageChanged(String packageName, int uid, String[] components) {
+
+    /**
+     * Direct reflection of {@link Intent#ACTION_PACKAGE_CHANGED
+     * Intent.ACTION_PACKAGE_CHANGED} being received, informing you of
+     * changes to the enabled/disabled state of components in a package
+     * and/or of the overall package.
+     *
+     * @param packageName The name of the package that is changing.
+     * @param uid The user ID the package runs under.
+     * @param components Any components in the package that are changing.  If
+     * the overall package is changing, this will contain an entry of the
+     * package name itself.
+     * @return Return true to indicate you care about this change, which will
+     * result in {@link #onSomePackagesChanged()} being called later.  If you
+     * return false, no further callbacks will happen about this change.  The
+     * default implementation returns true if this is a change to the entire
+     * package.
+     */
+    public boolean onPackageChanged(String packageName, int uid, String[] components) {
+        if (components != null) {
+            for (String name : components) {
+                if (packageName.equals(name)) {
+                    return true;
+                }
+            }
+        }
+        return false;
     }
     
     public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
@@ -189,7 +214,10 @@
      */
     public void onPackageAppeared(String packageName, int reason) {
     }
-    
+
+    /**
+     * Called when an existing package is updated or its disabled state changes.
+     */
     public void onPackageModified(String packageName) {
     }
     
@@ -328,9 +356,10 @@
             if (pkg != null) {
                 mModifiedPackages = mTempArray;
                 mTempArray[0] = pkg;
-                onPackageChanged(pkg, uid, components);
-                // XXX Don't want this to always cause mSomePackagesChanged,
-                // since it can happen a fair amount.
+                mChangeType = PACKAGE_PERMANENT_CHANGE;
+                if (onPackageChanged(pkg, uid, components)) {
+                    mSomePackagesChanged = true;
+                }
                 onPackageModified(pkg);
             }
         } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 4d41e42..3d7e1ff 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -536,7 +536,7 @@
             }
         }
 
-        private String getEnabledInputMethodsStr() {
+        public String getEnabledInputMethodsStr() {
             mEnabledInputMethodsStrCache = Settings.Secure.getStringForUser(
                     mResolver, Settings.Secure.ENABLED_INPUT_METHODS, mCurrentUserId);
             if (DEBUG) {
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 8ccc612..560227d 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -40,6 +40,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.Layout;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -49,7 +50,6 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
-import android.view.TouchDelegate;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
@@ -83,7 +83,8 @@
             ActionBar.DISPLAY_USE_LOGO |
             ActionBar.DISPLAY_HOME_AS_UP |
             ActionBar.DISPLAY_SHOW_CUSTOM |
-            ActionBar.DISPLAY_SHOW_TITLE;
+            ActionBar.DISPLAY_SHOW_TITLE |
+            ActionBar.DISPLAY_TITLE_MULTIPLE_LINES;
 
     private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.START | Gravity.CENTER_VERTICAL;
     
@@ -100,6 +101,7 @@
     private TextView mTitleView;
     private TextView mSubtitleView;
     private View mTitleUpView;
+    private ViewGroup mUpGoerFive;
 
     private Spinner mSpinner;
     private LinearLayout mListNavLayout;
@@ -137,10 +139,6 @@
 
     Window.Callback mWindowCallback;
 
-    private final Rect mTempRect = new Rect();
-    private int mMaxHomeSlop;
-    private static final int MAX_HOME_SLOP = 32; // dp
-
     private final AdapterView.OnItemSelectedListener mNavItemSelectedListener =
             new AdapterView.OnItemSelectedListener() {
         public void onItemSelected(AdapterView parent, View view, int position, long id) {
@@ -219,9 +217,11 @@
                 com.android.internal.R.styleable.ActionBar_homeLayout,
                 com.android.internal.R.layout.action_bar_home);
 
-        mHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
+        mUpGoerFive = (ViewGroup) inflater.inflate(
+                com.android.internal.R.layout.action_bar_up_container, this, false);
+        mHomeLayout = (HomeView) inflater.inflate(homeResId, mUpGoerFive, false);
 
-        mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
+        mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, mUpGoerFive, false);
         mExpandedHomeLayout.setUp(true);
         mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener);
         mExpandedHomeLayout.setContentDescription(getResources().getText(
@@ -250,16 +250,14 @@
         a.recycle();
         
         mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
-        mHomeLayout.setOnClickListener(mUpClickListener);
-        mHomeLayout.setClickable(true);
-        mHomeLayout.setFocusable(true);
+
+        mUpGoerFive.setOnClickListener(mUpClickListener);
+        mUpGoerFive.setClickable(true);
+        mUpGoerFive.setFocusable(true);
 
         if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
-
-        mMaxHomeSlop =
-                (int) (MAX_HOME_SLOP * context.getResources().getDisplayMetrics().density + 0.5f);
     }
 
     @Override
@@ -269,8 +267,8 @@
         mTitleView = null;
         mSubtitleView = null;
         mTitleUpView = null;
-        if (mTitleLayout != null && mTitleLayout.getParent() == this) {
-            removeView(mTitleLayout);
+        if (mTitleLayout != null && mTitleLayout.getParent() == mUpGoerFive) {
+            mUpGoerFive.removeView(mTitleLayout);
         }
         mTitleLayout = null;
         if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
@@ -551,19 +549,19 @@
     }
 
     public void setHomeButtonEnabled(boolean enable) {
-        mHomeLayout.setEnabled(enable);
-        mHomeLayout.setFocusable(enable);
+        mUpGoerFive.setEnabled(enable);
+        mUpGoerFive.setFocusable(enable);
         // Make sure the home button has an accurate content description for accessibility.
         if (!enable) {
-            mHomeLayout.setContentDescription(null);
-            mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+            mUpGoerFive.setContentDescription(null);
+            mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
         } else {
-            mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+            mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
             if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
-                mHomeLayout.setContentDescription(mContext.getResources().getText(
+                mUpGoerFive.setContentDescription(mContext.getResources().getText(
                         R.string.action_bar_up_description));
             } else {
-                mHomeLayout.setContentDescription(mContext.getResources().getText(
+                mUpGoerFive.setContentDescription(mContext.getResources().getText(
                         R.string.action_bar_home_description));
             }
         }
@@ -600,7 +598,7 @@
                 if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
                     initTitle();
                 } else {
-                    removeView(mTitleLayout);
+                    mUpGoerFive.removeView(mTitleLayout);
                 }
             }
 
@@ -608,8 +606,6 @@
                     (ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME)) != 0) {
                 final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
                 mTitleUpView.setVisibility(!showHome ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
-                mTitleLayout.setEnabled(!showHome && homeAsUp);
-                mTitleLayout.setClickable(!showHome && homeAsUp);
             }
 
             if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
@@ -620,6 +616,17 @@
                 }
             }
             
+            if (mTitleLayout != null &&
+                    (flagsChanged & ActionBar.DISPLAY_TITLE_MULTIPLE_LINES) != 0) {
+                if ((options & ActionBar.DISPLAY_TITLE_MULTIPLE_LINES) != 0) {
+                    mTitleView.setSingleLine(false);
+                    mTitleView.setMaxLines(2);
+                } else {
+                    mTitleView.setMaxLines(1);
+                    mTitleView.setSingleLine(true);
+                }
+            }
+
             requestLayout();
         } else {
             invalidate();
@@ -754,7 +761,8 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        addView(mHomeLayout);
+        mUpGoerFive.addView(mHomeLayout, 0);
+        addView(mUpGoerFive);
 
         if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
             final ViewParent parent = mCustomNavView.getParent();
@@ -776,8 +784,6 @@
             mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
             mTitleUpView = (View) mTitleLayout.findViewById(R.id.up);
 
-            mTitleLayout.setOnClickListener(mUpClickListener);
-
             if (mTitleStyleRes != 0) {
                 mTitleView.setTextAppearance(mContext, mTitleStyleRes);
             }
@@ -797,11 +803,9 @@
             final boolean showHome = (mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0;
             final boolean showTitleUp = !showHome;
             mTitleUpView.setVisibility(showTitleUp ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
-            mTitleLayout.setEnabled(homeAsUp && showTitleUp);
-            mTitleLayout.setClickable(homeAsUp && showTitleUp);
         }
 
-        addView(mTitleLayout);
+        mUpGoerFive.addView(mTitleLayout);
         if (mExpandedActionView != null ||
                 (TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) {
             // Don't show while in expanded mode or with empty text
@@ -821,6 +825,28 @@
         return mIsCollapsed;
     }
 
+    /**
+     * @return True if any characters in the title were truncated
+     */
+    public boolean isTitleTruncated() {
+        if (mTitleView == null) {
+            return false;
+        }
+
+        final Layout titleLayout = mTitleView.getLayout();
+        if (titleLayout == null) {
+            return false;
+        }
+
+        final int lineCount = titleLayout.getLineCount();
+        for (int i = 0; i < lineCount; i++) {
+            if (titleLayout.getEllipsisCount(i) > 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int childCount = getChildCount();
@@ -829,7 +855,16 @@
             for (int i = 0; i < childCount; i++) {
                 final View child = getChildAt(i);
                 if (child.getVisibility() != GONE &&
-                        !(child == mMenuView && mMenuView.getChildCount() == 0)) {
+                        !(child == mMenuView && mMenuView.getChildCount() == 0) &&
+                        child != mUpGoerFive) {
+                    visibleChildren++;
+                }
+            }
+
+            final int upChildCount = mUpGoerFive.getChildCount();
+            for (int i = 0; i < upChildCount; i++) {
+                final View child = mUpGoerFive.getChildAt(i);
+                if (child.getVisibility() != GONE) {
                     visibleChildren++;
                 }
             }
@@ -873,7 +908,8 @@
 
         HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
 
-        if (homeLayout.getVisibility() != GONE) {
+        int homeWidth = 0;
+        if (homeLayout.getVisibility() != GONE && homeLayout.getParent() == mUpGoerFive) {
             final ViewGroup.LayoutParams lp = homeLayout.getLayoutParams();
             int homeWidthSpec;
             if (lp.width < 0) {
@@ -881,10 +917,18 @@
             } else {
                 homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
             }
+
+            /*
+             * This is a little weird.
+             * We're only measuring the *home* affordance within the Up container here
+             * on purpose, because we want to give the available space to all other views before
+             * the title text. We'll remeasure the whole up container again later.
+             */
             homeLayout.measure(homeWidthSpec, exactHeightSpec);
-            final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getStartOffset();
-            availableWidth = Math.max(0, availableWidth - homeWidth);
-            leftOfCenter = Math.max(0, availableWidth - homeWidth);
+            homeWidth = homeLayout.getMeasuredWidth();
+            final int homeOffsetWidth = homeWidth + homeLayout.getStartOffset();
+            availableWidth = Math.max(0, availableWidth - homeOffsetWidth);
+            leftOfCenter = Math.max(0, availableWidth - homeOffsetWidth);
         }
         
         if (mMenuView != null && mMenuView.getParent() == this) {
@@ -986,9 +1030,13 @@
             availableWidth -= horizontalMargin + customView.getMeasuredWidth();
         }
 
-        if (mExpandedActionView == null && showTitle) {
-            availableWidth = measureChildView(mTitleLayout, availableWidth,
-                    MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
+        /*
+         * Measure the whole up container now, allowing for the full home+title sections.
+         * (This will re-measure the home view.)
+         */
+        availableWidth = measureChildView(mUpGoerFive, availableWidth + homeWidth,
+                MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
+        if (mTitleLayout != null) {
             leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
         }
 
@@ -1035,25 +1083,17 @@
         final int y = getPaddingTop();
 
         HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
-        boolean needsTouchDelegate = false;
-        int homeSlop = mMaxHomeSlop;
-        int homeRight = 0;
-        if (homeLayout.getVisibility() != GONE) {
-            final int startOffset = homeLayout.getStartOffset();
-            x += positionChild(homeLayout,
-                            next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl);
-            x = next(x, startOffset, isLayoutRtl);
-            needsTouchDelegate = homeLayout == mHomeLayout;
-            homeRight = x;
-        }
+        final int startOffset = homeLayout.getVisibility() != GONE &&
+                homeLayout.getParent() == mUpGoerFive ? homeLayout.getStartOffset() : 0;
+
+        // Position the up container based on where the edge of the home layout should go.
+        x += positionChild(mUpGoerFive,
+                next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl);
+        x = next(x, startOffset, isLayoutRtl);
 
         if (mExpandedActionView == null) {
             final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
                     (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
-            if (showTitle) {
-                x += positionChild(mTitleLayout, x, y, contentHeight, isLayoutRtl);
-                homeSlop = mTitleLayout.getWidth();
-            }
 
             switch (mNavigationMode) {
                 case ActionBar.NAVIGATION_MODE_STANDARD:
@@ -1063,7 +1103,6 @@
                         if (showTitle) {
                             x = next(x, mItemPadding, isLayoutRtl);
                         }
-                        homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
                         x += positionChild(mListNavLayout, x, y, contentHeight, isLayoutRtl);
                         x = next(x, mItemPadding, isLayoutRtl);
                     }
@@ -1071,7 +1110,6 @@
                 case ActionBar.NAVIGATION_MODE_TABS:
                     if (mTabScrollView != null) {
                         if (showTitle) x = next(x, mItemPadding, isLayoutRtl);
-                        homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
                         x += positionChild(mTabScrollView, x, y, contentHeight, isLayoutRtl);
                         x = next(x, mItemPadding, isLayoutRtl);
                     }
@@ -1176,7 +1214,6 @@
             final int customWidth = customView.getMeasuredWidth();
             customView.layout(xpos, ypos, xpos + customWidth,
                     ypos + customView.getMeasuredHeight());
-            homeSlop = Math.min(homeSlop, Math.max(xpos - homeRight, 0));
             x = next(x, customWidth, isLayoutRtl);
         }
 
@@ -1186,14 +1223,6 @@
             mProgressView.layout(mProgressBarPadding, -halfProgressHeight,
                     mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight);
         }
-
-        if (needsTouchDelegate) {
-            mTempRect.set(homeLayout.getLeft(), homeLayout.getTop(),
-                    homeLayout.getRight() + homeSlop, homeLayout.getBottom());
-            setTouchDelegate(new TouchDelegate(mTempRect, homeLayout));
-        } else {
-            setTouchDelegate(null);
-        }
     }
 
     @Override
@@ -1493,8 +1522,8 @@
             if (mExpandedActionView.getParent() != ActionBarView.this) {
                 addView(mExpandedActionView);
             }
-            if (mExpandedHomeLayout.getParent() != ActionBarView.this) {
-                addView(mExpandedHomeLayout);
+            if (mExpandedHomeLayout.getParent() != mUpGoerFive) {
+                mUpGoerFive.addView(mExpandedHomeLayout);
             }
             mHomeLayout.setVisibility(GONE);
             if (mTitleLayout != null) mTitleLayout.setVisibility(GONE);
@@ -1520,7 +1549,7 @@
             }
 
             removeView(mExpandedActionView);
-            removeView(mExpandedHomeLayout);
+            mUpGoerFive.removeView(mExpandedHomeLayout);
             mExpandedActionView = null;
             if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
                 mHomeLayout.setVisibility(VISIBLE);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a69870b..aafc4bf 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1702,6 +1702,13 @@
         android:description="@string/permdesc_stopAppSwitches"
         android:protectionLevel="signature|system" />
 
+    <!-- Allows an application to retrieve private information about
+         the current top activity, such as any assist context it can provide. -->
+    <permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"
+        android:label="@string/permlab_getTopActivityInfo"
+        android:description="@string/permdesc_getTopActivityInfo"
+        android:protectionLevel="signature" />
+
     <!-- Allows an application to retrieve the current state of keys and
          switches.  This is only for use by the system.
          @deprecated The API that used this permission has been removed. -->
diff --git a/core/res/res/layout-xlarge/screen_action_bar.xml b/core/res/res/layout-xlarge/screen_action_bar.xml
index 751d322..0b6122d 100644
--- a/core/res/res/layout-xlarge/screen_action_bar.xml
+++ b/core/res/res/layout-xlarge/screen_action_bar.xml
@@ -20,7 +20,8 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
-    android:fitsSystemWindows="true">
+    android:fitsSystemWindows="true"
+    android:splitMotionEvents="false">
     <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout-xlarge/screen_action_bar_overlay.xml b/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
index f2a1ea1..a95635e 100644
--- a/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
+++ b/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
@@ -23,7 +23,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/action_bar_overlay_layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:splitMotionEvents="false">
     <FrameLayout android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
diff --git a/core/res/res/layout/action_bar_home.xml b/core/res/res/layout/action_bar_home.xml
index fe58215..5341f3d 100644
--- a/core/res/res/layout/action_bar_home.xml
+++ b/core/res/res/layout/action_bar_home.xml
@@ -17,9 +17,7 @@
 <view xmlns:android="http://schemas.android.com/apk/res/android"
       class="com.android.internal.widget.ActionBarView$HomeView"
       android:layout_width="wrap_content"
-      android:layout_height="match_parent"
-      android:background="?android:attr/actionBarItemBackground"
-      android:animateLayoutChanges="true">
+      android:layout_height="match_parent">
     <ImageView android:id="@android:id/up"
                android:src="?android:attr/homeAsUpIndicator"
                android:layout_gravity="center_vertical|start"
diff --git a/core/res/res/layout/action_bar_title_item.xml b/core/res/res/layout/action_bar_title_item.xml
index df773eb..ccc5b07 100644
--- a/core/res/res/layout/action_bar_title_item.xml
+++ b/core/res/res/layout/action_bar_title_item.xml
@@ -16,10 +16,9 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
+              android:layout_height="match_parent"
               android:orientation="horizontal"
               android:paddingEnd="8dip"
-              android:background="?android:attr/actionBarItemBackground"
               android:enabled="false">
 
     <ImageView android:id="@android:id/up"
diff --git a/core/res/res/layout/action_bar_up_container.xml b/core/res/res/layout/action_bar_up_container.xml
new file mode 100644
index 0000000..c6fad64
--- /dev/null
+++ b/core/res/res/layout/action_bar_up_container.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="wrap_content"
+      android:layout_height="match_parent"
+      android:background="?android:attr/actionBarItemBackground"
+      android:gravity="center_vertical"
+      android:enabled="false">
+</LinearLayout>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index b0f1bc5..f0b2313 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -22,7 +22,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:fitsSystemWindows="true">
+    android:fitsSystemWindows="true"
+    android:splitMotionEvents="false">
     <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml
index 20a7db1..c8181d1 100644
--- a/core/res/res/layout/screen_action_bar_overlay.xml
+++ b/core/res/res/layout/screen_action_bar_overlay.xml
@@ -23,7 +23,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/action_bar_overlay_layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:splitMotionEvents="false">
     <FrameLayout android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index ad64eb6..029908b 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Laat \'n program toe om die huidige lae-vlak batteryverbruikdata te lees. Kan die program toelaat om gedetailleerde inligting te vind oor watter programme jy gebruik."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"verander batterystatistieke"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Laat die program toe om versamelde battery-statistieke te verander. Nie vir gebruik deur normale programme nie."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"haal programwerking-statistieke op"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Laat die program toe om versamelde programwerking-statistieke te herwin. Nie vir gebruik deur normale programme nie."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"verander programwerking-statistieke"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Laat die program toe om versamelde programwerking-statistieke te verander. Nie vir gebruik deur normale programme nie."</string>
     <string name="permlab_backup" msgid="470013022865453920">"beheerstelsel-rugsteun en -teruglaai"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 9fa0a06..5aa6d41 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"አንድ መተግበሪያ የአሁኑን የዝቅተኛ-ደረጃ ባትሪ አጠቃቀም ውሂብን እንዲያነብ ያስችላል። መተግበሪያው ስለሚጠቀሟቸው መተግበሪያዎች ዝርዝር መረጃ እንዲያገኝ ሊያስችለው ይችላል።"</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"የባትሪ ስታስቲክስን ይቀይራል"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"የተሰበሰቡ የባትሪ  ስታስቲክሶችን እንዲቀይር ለመተግበሪያው ያስችለዋል። ለመደበኛ መተግበሪያዎች ጥቅም አይደለም።"</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"የመተግበሪያ ክወናዎች ስታቲስቲክስን ሰርስረህ አውጣ"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"መተግበሪያው የተሰበሰቡ የክወና ስታስቲክሶችን ሰርስሮ እንዲያወጣ ይፈቅድለታል። ለመደበኛ መተግበሪያዎች ጥቅም ያልሆነ።"</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"የመተግበሪያ ክወናዎች ስታቲስቲክስን ይቀይሩ"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"መተግበሪያው የተሰበሰቡ የክወና ስታስቲክሶችን እንዲቀይር ይፈቅድሎታል። ለመደበኛ መተግበሪያዎች ጥቅም ያልሆነ።"</string>
     <string name="permlab_backup" msgid="470013022865453920">"የስርዓት መጠባበቂያን ተቆጣጠር እናእነበረበት መልስ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index d919829..50047b6 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"للسماح لتطبيق بقراءة البيانات الحالية التي تستهلك مستوى منخفضًا من البطارية. قد يتيح التطبيق معرفة معلومات تفصيلية عن التطبيقات التي تستخدمها."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"تعديل إحصاءات البطارية"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"للسماح للتطبيق بتعديل إحصاءات البطارية المجمّعة. ليس للاستخدام بواسطة التطبيقات العادية."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"استرداد إحصاءات عمليات التطبيق"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"للسماح للتطبيق باسترداد إحصاءات عمليات التطبيق المجمّعة. ليس للاستخدام بواسطة التطبيقات العادية."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"تعديل إحصاءات تشغيل التطبيق"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"للسماح للتطبيق بتعديل إحصاءات تشغيل التطبيق المجمّعة. ليس للاستخدام بواسطة التطبيقات العادية."</string>
     <string name="permlab_backup" msgid="470013022865453920">"التحكم في النسخة الاحتياطية للنظام واستعادتها"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 0b37f93..baf6456 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Прыкладанне можа счытваць бягучыя звесткi пры нiзкi зарад акумулятара. Прыкладанне можа знайсцi падрабязную iнфармацы. пра прыкладаннi, якiя вы выкарыстоўваеце."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"змяняць статыстыку батарэі"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Дазваляе прыкладанням змяняць сабраную статыстыку батарэi. Не патрабуецца для звычайных прыкладанняў."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"атрымлiваць статыстыку выкарыстання прыкладання"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Дазваляе прыкладанню атрымлiваць сабраную статыстыку выкарыстання прыкладання. Не для выкарыстання звычайнымі прыкладаннямі."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"змяняць статыстыку выкарыстання прыкладання"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Дазваляе прыкладанню змяняць сабраную статыстыку выкарыстання прыкладання. Не для выкарыстання звычайнымі прыкладаннямі."</string>
     <string name="permlab_backup" msgid="470013022865453920">"кантраляваць рэзервовае капіяванне і аднаўленне сістэмы"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 9bb46c1..1c85a7c 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Разрешава на приложението да чете текущите данни за работа при ниско ниво на батерията. Може да му разреши да намери подробна информация за ползваните от вас приложения."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"промяна на статистическите данни за батерията"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Разрешава на приложението да променя събраните статистически данни за батерията. Не е предназначено за нормални приложения."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"извличане на статистическите данни за операциите на приложението"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Разрешава на приложението да извлича събраните статистически данни за операциите си. Не е предназначено за нормални приложения."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"промяна на статистическите данни за операциите на приложението"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Разрешава на приложението да променя събраните статистически данни за операциите си. Не е предназначено за нормални приложения."</string>
     <string name="permlab_backup" msgid="470013022865453920">"контролиране на създаването и възстановяването на резервни копия на системата"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index eeda2cc..20ed8e3 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permet que l\'aplicació llegeixi l\'ús de dades actual quan hi ha poca bateria. Pot permetre que l\'aplicació recopili informació detallada sobre les aplicacions que fas servir."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modifica les estadístiques de la bateria"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permet que l\'aplicació modifiqui les estadístiques d\'ús de la bateria recopilades. No ho poden fer servir les aplicacions normals."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"recuperació d\'estadístiques d\'ús de l\'aplicació"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permet que l\'aplicació recuperi les estadístiques d\'ús de l\'aplicació recopilades. No indicat per a les aplicacions normals."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modifica les estadístiques d\'ús de l\'aplicació"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permet que l\'aplicació modifiqui les estadístiques d\'ús de l\'aplicació recopilades. No indicat per a les aplicacions normals."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlar la còpia de seguretat i restauració del sistema"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index f39e602..a08c0d9 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Umožňuje aplikaci číst aktuální podrobné údaje o využití baterie. Aplikace to může využít k získání podrobných informací o tom, které aplikace používáte."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"změna statistických údajů o baterii"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Umožňuje aplikaci upravit shromážděné statistiky o baterii. Toto oprávnění není určeno pro běžné aplikace."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"načtení statistik operací aplikace"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Umožňuje aplikaci načíst shromážděné statistiky operací aplikace. Toto oprávnění není určeno pro běžné aplikace."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"upravit statistiky operací aplikace"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Umožňuje aplikaci upravit shromážděné statistiky operací aplikace. Toto oprávnění není určeno pro běžné aplikace."</string>
     <string name="permlab_backup" msgid="470013022865453920">"ovládání zálohování a obnovy systému"</string>
@@ -408,19 +410,19 @@
     <string name="permlab_writeContacts" msgid="5107492086416793544">"úprava kontaktů"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Umožňuje aplikaci upravit údaje o kontaktech uložených v tabletu včetně toho, jak často voláte, posíláte e-maily nebo komunikujete jinými způsoby s konkrétními kontakty. Toto oprávnění aplikacím umožňuje mazat údaje o kontaktech."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Umožňuje aplikaci upravit údaje o kontaktech uložených v telefonu včetně toho, jak často voláte, posíláte e-maily nebo komunikujete jinými způsoby s konkrétními kontakty. Toto oprávnění aplikacím umožňuje mazat údaje o kontaktech."</string>
-    <string name="permlab_readCallLog" msgid="3478133184624102739">"číst seznam hovorů"</string>
+    <string name="permlab_readCallLog" msgid="3478133184624102739">"čtení seznamu hovorů"</string>
     <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Umožňuje aplikaci číst seznam hovorů v tabletu, včetně dat o příchozích a odchozích hovorech. Toto oprávnění umožňuje aplikaci ukládat údaje ze seznamu hovorů. Škodlivé aplikace mohou tyto údaje bez vašeho vědomí sdílet."</string>
     <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Umožňuje aplikaci číst seznam hovorů v telefonu, včetně dat o příchozích a odchozích hovorech. Toto oprávnění umožňuje aplikaci ukládat údaje ze seznamu hovorů. Škodlivé aplikace mohou tyto údaje bez vašeho vědomí sdílet."</string>
-    <string name="permlab_writeCallLog" msgid="8552045664743499354">"zapisovat seznam hovorů"</string>
+    <string name="permlab_writeCallLog" msgid="8552045664743499354">"zápis do seznamu hovorů"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Umožňuje aplikaci upravovat seznam hovorů vašeho tabletu, včetně dat o příchozích a odchozích hovorech. Škodlivé aplikace to mohou zneužít k vymazání nebo změnám seznamu hovorů."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Umožňuje aplikaci upravovat seznam hovorů vašeho telefonu, včetně dat o příchozích a odchozích hovorech. Škodlivé aplikace to mohou zneužít k vymazání nebo změnám seznamu hovorů."</string>
     <string name="permlab_readProfile" msgid="4701889852612716678">"čtení vaší vlastní vizitky"</string>
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Umožňuje aplikaci číst údaje v osobním profilu uložené v zařízení, například jméno nebo kontaktní údaje. Znamená to, že vás aplikace může identifikovat a odeslat údaje z profilu dalším aplikacím."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"úprava vaší vlastní vizitky"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Umožňuje aplikaci změnit nebo přidat údaje osobního profilu uložené v zařízení, například jméno nebo kontaktní údaje. Znamená to, že vás aplikace může identifikovat a odeslat údaje z profilu dalším aplikacím."</string>
-    <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"číst váš sociální stream"</string>
+    <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"čtení vašeho sociálního streamu"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Umožňuje aplikaci získat přístup k sociálním aktualizacím od vašich přátel a synchronizaci těchto aktualizací. Při sdílení informací buďte opatrní – toto oprávnění umožňuje aplikaci číst komunikaci mezi vámi a vašimi přáteli v sociálních sítích bez ohledu na její důvěrnost. Poznámka: Toto oprávnění nemusí platit pro všechny sociální sítě."</string>
-    <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"zapisovat do vašeho sociálního streamu"</string>
+    <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"zápis do sociálního streamu"</string>
     <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Umožňuje aplikaci zobrazit sociální aktualizace od vašich přátel. Při sdílení informací buďte opatrní – aplikace s tímto oprávněním může vytvářet zprávy, které zdánlivě pochází od vašich přátel. Poznámka: Toto oprávnění nemusí platit pro všechny sociální sítě."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"čtení událostí kalendáře a důvěrné informace"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Umožňuje aplikaci číst všechny události kalendáře uložené v tabletu, včetně událostí přátel nebo spolupracovníků. Aplikace s tímto oprávněním může sdílet nebo ukládat údaje v kalendáři bez ohledu na důvěrnost nebo citlivost těchto údajů."</string>
@@ -503,8 +505,8 @@
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"Umožňuje aplikaci ovládat telefonní funkce zařízení. Aplikace s tímto oprávněním smí bez upozornění přepínat sítě, zapínat a vypínat bezdrátový modul telefonu a podobně."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"čtení stavu a identity telefonu"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Umožňuje aplikaci získat přístup k telefonním funkcím zařízení. Toto oprávnění umožňuje aplikaci zjistit telefonní číslo telefonu, identifikační čísla zařízení, zda zrovna probíhá hovor, a vzdálené číslo, ke kterému je hovor připojen."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zabránění přechodu tabletu do režimu spánku"</string>
-    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"zabránění přechodu telefonu do režimu spánku"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"bránění přechodu tabletu do režimu spánku"</string>
+    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"bránění přechodu telefonu do režimu spánku"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Umožňuje aplikaci zabránit přechodu tabletu do režimu spánku."</string>
     <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"Umožňuje aplikaci zabránit přechodu telefonu do režimu spánku."</string>
     <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"zapnutí či vypnutí tabletu"</string>
@@ -528,12 +530,12 @@
     <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Umožňuje aplikaci změnit časové pásmo telefonu."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"role služby AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="1948455552333615954">"Umožňuje aplikaci volat funkce AccountAuthenticator."</string>
-    <string name="permlab_getAccounts" msgid="1086795467760122114">"vyhledání účtů v zařízení"</string>
+    <string name="permlab_getAccounts" msgid="1086795467760122114">"vyhledávání účtů v zařízení"</string>
     <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Umožňuje aplikaci získat seznam účtů v tabletu. Mohou sem patřit i účty vytvořené aplikacemi, které jste nainstalovali."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Umožňuje aplikaci získat seznam účtů v telefonu. Mohou sem patřit i účty vytvořené aplikacemi, které jste nainstalovali."</string>
     <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"vytváření účtů a nastavení hesel"</string>
     <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Umožňuje aplikaci používat funkce aplikace AccountManager související s ověřováním účtů – včetně vytváření účtů a získávání a nastavování hesel."</string>
-    <string name="permlab_manageAccounts" msgid="4983126304757177305">"přidání nebo odebrání účtů"</string>
+    <string name="permlab_manageAccounts" msgid="4983126304757177305">"přidávání nebo odebírání účtů"</string>
     <string name="permdesc_manageAccounts" msgid="8698295625488292506">"Umožňuje aplikaci provádět operace, jako je přidávání nebo odebírání účtů nebo mazání jejich hesel."</string>
     <string name="permlab_useCredentials" msgid="235481396163877642">"používání účtů v zařízení"</string>
     <string name="permdesc_useCredentials" msgid="7984227147403346422">"Umožňuje aplikaci požadovat ověřovací tokeny."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 45f551c..723f95e 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Tillader, at en applikation læser de aktuelle data for batteriforbruget. Kan tillade, at applikationen henter detaljerede oplysninger om, hvilke apps du bruger."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"rediger batteristatistikker"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Tillader, at appen kan ændre indsamlede batteristatistikker. Anvendes ikke af normale apps."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"hent statistikker for handlinger i appen"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Tillader, at appen indhenter statistikker for handlinger i applikationen. Denne handling bruges ikke i almindelige apps."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"lav ændringer i statistik for handlinger i appen"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Tillader, at appen kan ændre indsamlede statistikker for handlinger i applikationen. Dette kan ikke bruges af almindelige apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontroller sikkerhedskopiering af system, og gendan"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 1ef42f6..4cffe2f 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Ermöglicht einer Anwendung, den momentan niedrigen Akkustand zu erkennen. Unter Umständen erhält die App detaillierte Informationen darüber, welche Apps Sie verwenden."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"Akkudaten ändern"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Ermöglicht der App, erfasste Akkudaten zu ändern. Nicht für normale Apps vorgesehen."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"App-Vorgangsstatistiken abrufen"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Ermöglicht der App, erfasste App-Vorgangsstatistiken abzurufen. Kann nicht von normalen Apps verwendet werden."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"App-Vorgangsstatistiken ändern"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Ermöglicht der App, erfasste App-Vorgangsstatistiken zu ändern. Kann nicht von normalen Apps verwendet werden"</string>
     <string name="permlab_backup" msgid="470013022865453920">"Systemsicherung und -wiederherstellung kontrollieren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index f3333dd..e0415aa 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Επιτρέπει σε μια εφαρμογή να διαβάζει τα δεδομένα τρέχουσας χαμηλού επιπέδου χρήσης μπαταρίας. Ενδέχεται να επιτρέπει στην εφαρμογή να εντοπίσει λεπτομερείς πληροφορίες σχετικά με τις εφαρμογές που χρησιμοποιείτε."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"τροποποίηση στατιστικών στοιχείων μπαταρίας"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Επιτρέπει στην εφαρμογή την τροποποίηση στατιστικών στοιχείων μπαταρίας που έχουν συλλεχθεί. Δεν πρέπει να χρησιμοποιείται από συνήθεις εφαρμογές."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"ανάκτηση στατιστικών στοιχείων λειτουργίας για εφαρμογές"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Επιτρέπει στην εφαρμογή την ανάκτηση των στατιστικών στοιχείων λειτουργίας για τις εφαρμογές που έχουν συλλεχθεί. Δεν προορίζεται για χρήση από κανονικές εφαρμογές."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"τροποποίηση στατιστικών στοιχείων λειτουργιών εφαρμογών"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Επιτρέπει στην εφαρμογή την τροποποίηση των στατιστικών στοιχείων λειτουργίας εφαρμογών που έχουν συλλεχθεί. Δεν προορίζεται για χρήση από κανονικές εφαρμογές."</string>
     <string name="permlab_backup" msgid="470013022865453920">"αντίγραφο ασφαλείας και επαναφορά συστήματος"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 538dd66..c093c21 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Allows an application to read the current low-level battery use data. May allow the application to find out detailed information about which apps you use."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modify battery statistics"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Allows the app to modify collected battery statistics. Not for use by normal apps."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"retrieve app ops statistics"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Allows the app to retrieve collected application operation statistics. Not for use by normal apps."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modify app ops statistics"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Allows the app to modify collected component usage statistics. Not for use by normal apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"control system back up and restore"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 8fc1450..948f18d 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite a una aplicación leer los datos actuales de uso de batería de bajo nivel. Puede permitir a la aplicación buscar información detallada sobre las aplicaciones que usas."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modificar las estadísticas de la batería"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite a la aplicación modificar las estadísticas recopiladas de la batería. Las aplicaciones normales no deben utilizarlo."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"Recuperar estadísticas de operaciones de la aplicación"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permite que la aplicación recupere las estadísticas recopiladas de operación de la aplicación. Las aplicaciones normales no deben utilizar este permiso."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modificar estadísticas de uso de aplicaciones"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permite que la aplicación modifique las estadísticas recopiladas sobre el uso de aplicaciones. Las aplicaciones normales no deben utilizar este permiso."</string>
     <string name="permlab_backup" msgid="470013022865453920">"copia de seguridad y restauración del sistema de control"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 17a7e86..47a2b00 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite que una aplicación consulte los datos actuales de uso de batería de nivel inferior. Puede permitir que la aplicación obtenga información detallada sobre las aplicaciones que utilizas."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modificar estadísticas de la batería"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite que la aplicación modifique las estadísticas recopiladas sobre la batería. Las aplicaciones normales no deben usar este permiso."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"recuperar estadísticas de operaciones de aplicaciones"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permite que la aplicación recupere las estadísticas recopiladas sobre operaciones de aplicaciones. Las aplicaciones normales no deben usar este permiso."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modificar estadísticas de operaciones de aplicaciones"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permite que la aplicación modifique las estadísticas recopiladas sobre operaciones de aplicaciones. Las aplicaciones normales no deben usar este permiso."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlar las copias de seguridad y las restauraciones del sistema"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 8b4408a..bd9464b 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Lubab rakendusel lugeda madala akutaseme kasutusandmeid. Võib lubada rakendusel hankida üksikasjalikku teavet selle kohta, mis rakendusi te kasutate."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"aku statistika muutmine"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Võimaldab rakendusel muuta aku kohta kogutud statistikat. Mitte kasutada tavarakenduste puhul."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"rakenduse tööstatistika hankimine"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Võimaldab rakendusel hankida kogutud rakenduse tööstatistikat. Mitte kasutada tavarakenduste puhul."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"rakenduse tööstatistika muutmine"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Võimaldab rakendusel muuta kogutud rakenduse tööstatistikat. Mitte kasutada tavarakenduste puhul."</string>
     <string name="permlab_backup" msgid="470013022865453920">"juhi süsteemi varundust ja taastet"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 3f2da2c..067d9d8 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"به یک برنامه کاربردی اجازه می‌دهد که داده‌های استفاده کننده از میزان باتری کم کنونی را بخواند. این کار ممکن است به برنامه این امکان را بدهد که اطلاعات جزئی درباره برنامه‌هایی که استفاده می‌کنید، بدست آورد."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"اصلاح آمار باتری"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"به برنامه اجازه می‎دهد تا آمار جمع‌آوری شده باتری را تغییر دهد. برای استفاده برنامه‎های عادی نیست."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"بازیابی آمار مربوط به کارکرد برنامه"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"به برنامه امکان می‌دهد آمار جمع‌آوری شده مربوط به عملکرد برنامه را بازیابی کند. برای استفاده توسط برنامه‌های معمولی، در نظر گرفته نشده است."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"تغییر آمار کارکرد برنامه"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"به برنامه اجازه تغییر آمار کارکرد جمع‌آوری شده از برنامه را می‌دهد. برای استفاده توسط برنامه‌های معمولی نیست."</string>
     <string name="permlab_backup" msgid="470013022865453920">"کنترل نسخهٔ پشتیبان سیستم و بازیابی"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 7573f41..61a09f9 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Antaa sovelluksen lukea nykyisiä alhaisen tason akunkäyttötietoja. Sovellus saattaa saada tietoonsa, mitä sovelluksia käytät."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"muokkaa akkutilastoja"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Antaa sovelluksen muokata kerättyjä akkutilastoja. Ei tavallisten sovellusten käyttöön."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"nouda sovellusten toimintatilastoja"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Antaa sovelluksen noutaa kerättyjä sovellusten toimintatilastoja. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"sovellusten käyttötilastojen muokkaus"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Antaa sovelluksen muokata kerättyjä sovellusten käyttötilastoja. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_backup" msgid="470013022865453920">"hallitse järjestelmän varmuuskopiointia ja palauttamista"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index e4aad26..67f7644 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permet à une application de lire les données de consommation actuelles indiquant le faible niveau de la batterie. Permet éventuellement à l\'application d\'obtenir des informations détaillées sur les applications que vous utilisez."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modifier les statistiques de la batterie"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permet à l\'application de modifier les statistiques collectées concernant la batterie. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"récupérer les statistiques de fonctionnement des applications"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permet à l\'application de récupérer les statistiques de fonctionnement des applications recueillies. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modifier les statistiques de fonctionnement des applications"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permet à l\'application de modifier les statistiques de fonctionnement des applications collectées. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
     <string name="permlab_backup" msgid="470013022865453920">"contrôler la sauvegarde et la restauration du système"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f4e2d3e..5007669 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"एप्लिकेशन को वर्तमान निम्न-स्तरीय बैटरी उपयोग डेटा पढ़ने देती है. एप्लिकेशन को आपके द्वारा उपयोग किए जाने वाले एप्लिकेशन के बारे में विस्तृत जानकारी ढूंढने दे सकती है."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"बैटरी के आंकड़े संशोधित करें"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"एप्‍लिकेशन को बैटरी के संकलित आंकड़ों को संशोधित करने देती है. सामान्‍य एप्‍लिकेशन के द्वारा उपयोग करने के लिए नहीं."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"एप्लिकेशन संचालन आंकड़े प्राप्त करें"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"एप्लिकेशन को संकलित एप्लिकेशन संचालन आंकड़े प्राप्त करने देता है. सामान्य एप्लिकेशन के द्वारा उपयोग के लिए नहीं."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"एप्लिकेशन कार्यवाही के आंकड़े बदलें"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"एप्लिकेशन को एप्लिकेशन कार्यवाही के एकत्रित आंकड़े बदलने देता है. सामान्य एप्लिकेशन के द्वारा उपयोग करने के लिए नहीं."</string>
     <string name="permlab_backup" msgid="470013022865453920">"सिस्‍टम बैकअप नियंत्रित और पुनर्स्‍थापित करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index a7085f4..e30410f 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Aplikacija može očitavati podatke o trenutačnoj potrošnji baterije na niskoj razini. Tako može doznati detaljne informacije o aplikacijama koje upotrebljavate."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"izmjena statistike o bateriji"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Omogućuje aplikaciji promjenu prikupljene statistike o potrošnji baterije. Nije namijenjena uobičajenim aplikacijama."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"dohvaćanje statistike o radu aplikacije"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Aplikaciji omogućuje dohvaćanje prikupljene statistike o radu aplikacije. Nije namijenjena uobičajenim aplikacijama."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"izmjena statistike o radu aplikacije"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Aplikaciji omogućuje promjenu prikupljene statistike o radu aplikacije. Nije namijenjena uobičajenim aplikacijama."</string>
     <string name="permlab_backup" msgid="470013022865453920">"sigurnosna kopija i oporavak nadzornog sustava"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 840ed06..6b64637 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Lehetővé teszi egy alkalmazás számára, hogy leolvassa az aktuális alacsony szintű akkumulátorhasználatra vonatkozó adatokat. Ezáltal az alkalmazás részletes adatokhoz jut az Ön által használt alkalmazásokról."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"akkumulátorstatisztikák módosítása"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Lehetővé teszi az alkalmazás számára az összegyűjtött akkumulátorhasználati statisztikák módosítását. Normál alkalmazások nem használhatják."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"alkalmazásműveleti statisztikák lekérdezése"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Lehetővé teszi az alkalmazás számára az összegyűjtött alkalmazásműveleti statisztikák lekérdezését. Normál alkalmazások nem használhatják."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"alkalmazásműveleti statisztikák módosítása"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Lehetővé teszi az alkalmazás számára az összegyűjtött alkalmazásműveleti statisztikák módosítását. Normál alkalmazások nem használhatják."</string>
     <string name="permlab_backup" msgid="470013022865453920">"rendszer biztonsági mentésének és helyreállításának vezérlése"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 638528f..3fb0b21 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Mengizinkan aplikasi membaca data penggunaan baterai tingkat rendah. Dapat mengizinkan aplikasi mencari informasi mendetail tentang aplikasi mana yang Anda gunakan."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"ubah statistik baterai"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Mengizinkan aplikasi mengubah statistik baterai yang dikumpulkan. Tidak untuk digunakan oleh aplikasi normal."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"mengambil statistik pengoperasian aplikasi"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Mengizinkan aplikasi mengambil statistik pengoperasian aplikasi yang dikumpulkan. Tidak untuk digunakan oleh aplikasi normal."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"memodifikasi statistik pengoperasian aplikasi"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Mengizinkan aplikasi memodifikasi statistik pengoperasian aplikasi yang dikumpulkan. Tidak untuk digunakan oleh aplikasi normal."</string>
     <string name="permlab_backup" msgid="470013022865453920">"mengontrol cadangan dan pemulihan sistem"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index d3eaa61..98f8972 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Consente a un\'applicazione di leggere i dati di utilizzo della batteria di basso livello correnti. Potrebbe consentire all\'applicazione di trovare informazioni dettagliate sulle applicazioni che utilizzi."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modifica statistiche batteria"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Consente all\'applicazione di modificare le statistiche raccolte sulla batteria. Da non usare per normali applicazioni."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"recupero statistiche funzion. app"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Consente all\'applicazione di recuperare le statistiche raccolte sul funzionamento dell\'applicazione. Da non usare per normali applicazioni."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modifica statistiche funzionamento app"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Consente all\'applicazione di modificare le statistiche raccolte sul funzionamento dell\'applicazione. Da non usare per normali applicazioni."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controllo del backup di sistema e ripristino"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 784a893..d38710a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"מאפשר ליישום לקרוא את נתוני השימוש הנוכחיים של הסוללה ברמה נמוכה. עשוי לאפשר ליישום לגלות מידע מפורט לגבי היישומים שבהם אתה משתמש."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"שינוי הנתונים הסטטיסטיים של הסוללה"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"מאפשר ליישום לשנות נתונים סטטיסטיים שנאספו לגבי הסוללה. לא מיועד לשימוש על ידי יישומים רגילים."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"אחזור נתונים סטטיסטיים של פעולות יישום"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"הרשאה זו מאפשרת ליישום לאחזר נתונים סטטיסטיים שנאספו לגבי פעולות יישום. לא מיועד לשימוש על ידי יישומים רגילים."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"שינוי סטטיסטיקת ההפעלה של היישום"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"מאפשר ליישום לשנות נתונים סטטיסטיים שנאספו לגבי הפעלתו. לא מיועד לשימוש על ידי יישומים רגילים."</string>
     <string name="permlab_backup" msgid="470013022865453920">"שלוט בגיבוי ובשחזור של המערכת"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index e53ff29..9d5a1a5 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"現在の電池消費量の低レベルデータを読み取ることをアプリに許可します。このアプリが、使用しているアプリの詳細情報を確認できるようになります。"</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"電池統計情報の変更"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"電池に関して収集した統計情報の変更をアプリに許可します。通常のアプリでは使用しません。"</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"アプリの操作状況に関する統計情報の取得"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"アプリの操作状況に関して収集された統計情報の取得をアプリに許可します。通常のアプリでは使用しません。"</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"アプリの操作状況に関する統計情報の変更"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"アプリの操作状況に関して収集された統計情報の変更をアプリに許可します。通常のアプリでは使用しません。"</string>
     <string name="permlab_backup" msgid="470013022865453920">"システムのバックアップと復元を制御する"</string>
@@ -785,11 +787,11 @@
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"ユーザーガイドをご覧いただくか、お客様サポートにお問い合わせください。"</string>
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIMカードはロックされています。"</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIMカードのロック解除中..."</string>
-    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"正しくないパスワードを<xliff:g id="NUMBER_0">%d</xliff:g>回入力しました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"正しくないPINを<xliff:g id="NUMBER_0">%d</xliff:g>回入力しました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、タブレットのロック解除にGoogleへのログインが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、携帯端末のロック解除にGoogleへのログインが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"正しくないパスワードを<xliff:g id="NUMBER_0">%d</xliff:g>回入力しました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"正しくないPINを<xliff:g id="NUMBER_0">%d</xliff:g>回入力しました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、タブレットのロック解除にGoogleへのログインが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、携帯端末のロック解除にGoogleへのログインが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒後にもう一度お試しください。"</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"タブレットのロック解除に<xliff:g id="NUMBER_0">%d</xliff:g>回失敗しました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回失敗すると、タブレットは工場出荷状態にリセットされ、ユーザーのデータはすべて失われます。"</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"端末のロック解除に<xliff:g id="NUMBER_0">%d</xliff:g>回失敗しました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回失敗すると、端末は工場出荷状態にリセットされ、ユーザーのデータはすべて失われます。"</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"タブレットのロック解除を<xliff:g id="NUMBER">%d</xliff:g>回失敗しました。タブレットを工場出荷状態にリセットします。"</string>
@@ -1420,7 +1422,7 @@
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"パターンが正しくありません"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"パスワードが正しくありません"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"PINが正しくありません"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g>秒後にもう一度お試しください。"</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"パターンを入力"</string>
     <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PINを入力"</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"PINを入力"</string>
@@ -1442,15 +1444,15 @@
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"ユーザー名またはパスワードが無効です。"</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ユーザー名またはパスワードを忘れた場合は"\n" "<b>"google.com/accounts/recovery"</b>" にアクセスしてください。"</string>
     <string name="kg_login_checking_password" msgid="1052685197710252395">"アカウントをチェックしています…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"PINの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"パスワードの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"PINの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"パスワードの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度お試しください。"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"タブレットのロック解除に<xliff:g id="NUMBER_0">%d</xliff:g>回失敗しました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回失敗すると、タブレットは出荷時設定にリセットされ、ユーザーのデータはすべて失われます。"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"携帯端末のロック解除に<xliff:g id="NUMBER_0">%d</xliff:g>回失敗しました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回失敗すると、端末は出荷時設定にリセットされ、ユーザーのデータはすべて失われます。"</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"タブレットのロック解除を<xliff:g id="NUMBER">%d</xliff:g>回失敗しました。タブレットは出荷時設定にリセットされます。"</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"携帯端末のロック解除を<xliff:g id="NUMBER">%d</xliff:g>回失敗しました。端末は出荷時設定にリセットされます。"</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、タブレットのロック解除にメールアカウントが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、携帯端末のロック解除にメールアカウントが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、タブレットのロック解除にメールアカウントが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、携帯端末のロック解除にメールアカウントが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒後にもう一度お試しください。"</string>
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"削除"</string>
     <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"安全レベルを超えるまで音量を上げますか?"\n"大音量で長時間聞き続けると、聴力を損なう恐れがあります。"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 17006fd..cc7a934 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"애플리케이션이 현재의 낮은 수준 배터리 사용 데이터를 읽을 수 있도록 합니다. 이 경우 애플리케이션이 내가 사용하는 앱에 대한 세부정보를 파악할 수도 있습니다."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"배터리 통계 수정"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"앱이 수집된 배터리 통계를 수정할 수 있도록 허용합니다. 일반 앱에서는 사용하지 않습니다."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"앱 운영 통계 검색"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"앱이 수집된 애플리케이션 운영 통계를 검색하도록 합니다. 일반 앱에서는 사용하지 않습니다."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"앱 운영 통계 수정"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"앱이 수집된 애플리케이션 운영 통계를 수정하도록 합니다. 일반 앱에서는 사용하지 않습니다."</string>
     <string name="permlab_backup" msgid="470013022865453920">"시스템 백업 및 복원 관리"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 7700f1c..682958e 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Leidžiama programai skaityti dabartinius išsikraunančio akumuliatoriaus naudojimo duomenis. Gali būti leidžiama programai sužinoti išsamią informaciją apie jūsų naudojamas programas."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"keisti akumuliatoriaus statistiką"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Leidžiama programai keisti surinktą akumuliatoriaus statistiką. Neskirta naudoti įprastoms programoms."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"nuskaityti programos naudojimo statistiką"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Programai leidžiama nuskaityti surinktą programos naudojimo statistiką. Neskirta naudoti įprastoms programoms."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"keisti programos naudojimo statistiką"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Programai leidžiama keisti surinktą programos naudojimo statistiką. Neskirta naudoti įprastoms programoms."</string>
     <string name="permlab_backup" msgid="470013022865453920">"valdyti sistemos atsarginę kopiją ir atkūrimą"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 040beb1..ab05871 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Ļauj lietojumprogrammai lasīt pašreizējos zema akumulatora enerģijas patēriņa datus. Var atļaut lietojumprogrammai iegūt detalizētu informāciju par to, kuras lietotnes izmantojat."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"akumulatora statistikas pārveidošana"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Ļauj lietotnei pārveidot apkopoto statistiku par akumulatoru. Atļauja neattiecas uz parastām lietotnēm."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"Izgūt lietotnes darbību statistiku"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Ļauj lietotnei izgūt apkopoto statistiku par lietojumprogrammas darbību. Atļauja neattiecas uz parastām lietotnēm."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"Pārveidot lietotnes darbības statistiku"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Ļauj lietotnei pārveidot apkopoto statistiku par lietojumprogrammas darbību. Atļauja neattiecas uz parastām lietotnēm."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrolēt sistēmas dublējumu un atjaunošanu"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 436a1db..ac1bcd5 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Membenarkan aplikasi membaca data penggunaan bateri tahap rendah semasa. Boleh membenarkan aplikasi untuk mencari maklumat terperinci tentang apl yang anda gunakan."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"ubah suai statistik bateri"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Membenarkan apl mengubah suai statistik bateri yang dikumpul. Bukan untuk penggunaan apl normal."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"dapatkan semula statistik pengendalian apl"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Membenarkan apl mendapatkan semula statistik pengendalian aplikasi yang dikumpul. Bukan untuk kegunaan apl biasa."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"ubah suai apl ops statistik"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Membenarkan apl mengubah suai statistik operasi aplikasi yang dikumpul. Bukan untuk kegunaan apl biasa."</string>
     <string name="permlab_backup" msgid="470013022865453920">"sandaran dan pemulihan sistem kawalan"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 3a7cd46..095b75d 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Lar apper lese gjeldende data på lavt nivå om batteribruk. Kan også la appen finne ut detaljert informasjon om hvilke apper du bruker."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"endre batteristatistikk"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Lar appen endre innsamlet batteristatistikk. Ikke beregnet på vanlige apper."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"hente bruksstatistikk for appen"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Lar appen hente innsamlet bruksstatistikk. Ikke beregnet på vanlige apper."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"endre bruksstatistikk for appen"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Lar appen endre innsamlet bruksstatistikk. Ikke beregnet på vanlige apper."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrollere sikkerhetskopiering og gjenoppretting"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 1dd9fe9..55ee0c9 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Hiermee kan de app het huidige accugebruik voor gegevens op laag niveau lezen. Een app kan hierdoor mogelijk gedetailleerde informatie achterhalen over de door u gebruikte apps."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"accustatistieken aanpassen"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Hiermee kan de app verzamelde accustatistieken wijzigen. Niet voor gebruik door normale apps."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"bewerkingsstatistieken van apps ophalen"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Hiermee kan de app verzamelde bewerkingsstatistieken van apps ophalen. Niet voor gebruik door normale apps."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"bewerkingsstatistieken van apps wijzigen"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Hiermee kan de app verzamelde bewerkingsstatistieken van apps wijzigen. Niet voor gebruik door normale apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"systeemback-up en -herstel beheren"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 8123bea..ee2722f 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Zezwala aplikacji na odczytywanie bieżących danych niskiego poziomu o wykorzystaniu baterii. Możliwe jest wtedy zbieranie przez aplikację szczegółowych danych o używanych aplikacjach."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"zmienianie statystyk dotyczących baterii"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Zezwala aplikacji na modyfikowanie zebranych statystyk dotyczących baterii. Nieprzeznaczone dla zwykłych aplikacji."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"pobieranie statystyk działania aplikacji"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Zezwala aplikacji na pobieranie zebranych statystyk działania aplikacji. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modyfikowanie statystyk działania aplikacji"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Zezwala aplikacji na modyfikowanie zebranych statystyk działania aplikacji. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrolowanie tworzenia i przywracania kopii zapasowych systemu"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 66879ee..ad6de6f 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite que uma aplicação leia os atuais dados de utilização da bateria de baixo nível. Poderá permitir que a aplicação encontre informações detalhadas sobre as aplicações que utiliza."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modificar estatísticas da bateria"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite que a aplicação modifique as estatísticas recolhidas sobre a bateria. Não se destina a utilização por aplicações normais."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"obter estatísticas de utilização da aplicação"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permite que a aplicação obtenha as estatísticas de utilização da aplicação recolhidas. Não se destina a utilização por aplicações normais."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modificar estatísticas de utilização da aplicação"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permite que a aplicação modifique as estatísticas de utilização de aplicação recolhidas. Não se destina a utilização por aplicações normais."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlar a cópia de segurança e restauro do sistema"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index b9167ef..6ace353 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite que o aplicativo leia os dados de uso da bateria de baixo nível atuais. Pode fornecer ao aplicativo informações detalhadas sobre os aplicativos usados por você."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modificar estatísticas da bateria"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite que o aplicativo modifique as estatísticas coletadas da bateria. Não deve ser usado em aplicativos normais."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"recuperar estatísticas de operações de aplicativos"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permite que o aplicativo recupere as estatísticas de operações de aplicativos. Não deve ser usado em aplicativos normais."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modificar estatísticas de operações de aplicativos"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permite que o aplicativo modifique as estatísticas de operações de aplicativos. Não deve ser usado em aplicativos normais."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlar backup e restauração do sistema"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 8d8d882..589df10 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -477,6 +477,10 @@
     <skip />
     <!-- no translation found for permdesc_updateBatteryStats (6862817857178025002) -->
     <skip />
+    <!-- no translation found for permlab_getAppOpsStats (1508779687436585744) -->
+    <skip />
+    <!-- no translation found for permdesc_getAppOpsStats (6243887041577912877) -->
+    <skip />
     <!-- no translation found for permlab_updateAppOpsStats (8829097373851521505) -->
     <skip />
     <!-- no translation found for permdesc_updateAppOpsStats (50784596594403483) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 30276cb..5952d2f 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite unei aplicaţii să citească datele actuale privind utilizarea la nivel redus a bateriei. Cu această permisiune, aplicaţia poate afla informaţii detaliate despre aplicaţiile pe care le utilizaţi."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modifică statistici referitoare la baterie"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite aplicaţiei să modifice statisticile colectate despre baterie. Nu se utilizează de aplicaţiile obişnuite."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"preluarea statisticilor privind operațiile aplicației"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permite aplicației să preia statisticile colectate privind operațiile aplicației. Nu se utilizează de aplicațiile obișnuite."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modificarea statisticilor privind utilizarea aplicației"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permite aplicației să modifice statisticile colectate despre utilizarea aplicației. Nu se utilizează de aplicațiile obișnuite."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlare copiere de rezervă şi restabilire a sistemului"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index bbfd928..c2685db 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Разрешает приложению получать данные об использовании батареи на низшем уровне. В результате оно может иметь доступ к информации об используемых вами программах."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"изменять статистику батареи"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Приложение сможет изменять собранную статистику использования заряда батареи. Это разрешение не используется обычными приложениями."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"получать статистику операций в приложениях"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Приложение сможет получать собранную статистику операций в приложениях. Это разрешение не используется обычными программами."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"изменять статистику операций в приложениях"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Приложение сможет изменять собранную статистику операций в приложениях. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_backup" msgid="470013022865453920">"управление резервным копированием и восстановлением системы"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index c0147eb..51624d2 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Umožňuje aplikácii čítať aktuálne údaje nízkej úrovne o používaní batérie. Pomocou tejto funkcie môže aplikácia zistiť podrobnosti o tom, ktoré aplikácie používate."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"zmena štatistických údajov o batérii"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Umožňuje aplikácii zmeniť zhromaždené štatistické údaje o batérii. Bežné aplikácie toto nastavenie nepoužívajú."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"získať štatistické údaje o fungovaní aplikácií"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Umožňuje aplikácii získať zhromaždené štatistické údaje o fungovaní aplikácií. Bežné aplikácie toto nastavenie nepoužívajú."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"upraviť štatistické údaje o fungovaní aplikácií"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Umožňuje aplikácii zmeniť zhromaždené štatistické údaje o fungovaní aplikácií. Bežné aplikácie toto nastavenie nepoužívajú."</string>
     <string name="permlab_backup" msgid="470013022865453920">"Ovládať zálohovanie a obnovu systému"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 5e90928..2d9303c 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Aplikaciji omogoča branje podatkov o trenutni nizki napolnjenosti akumulatorja. Aplikaciji lahko tudi dovoli dostop do podrobnosti o tem, katere aplikacije uporabljate."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"spreminjanje statističnih podatkov o akumulatorju"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Aplikaciji omogoča spreminjanje zbranih statističnih podatkov o akumulatorju. Ni primerno za uporabo z običajnimi aplikacijami."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"pridobi statistične podatke o delovanju aplikacij"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Aplikaciji dovoli pridobivanje zbranih statističnih podatkov o delovanju aplikacij. Ni za uporabo v navadnih aplikacijah."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"spreminjanje statističnih podatkov o delovanju aplikacije"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Aplikaciji dovoli spreminjanje zbranih statističnih podatkov o delovanju aplikacij. Ni za uporabo v navadnih aplikacijah."</string>
     <string name="permlab_backup" msgid="470013022865453920">"nadzor varnostnega kopiranja sistema in obnovitev"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 736a545..bbe2059 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Дозвољава апликацији да чита опште податке о тренутној употреби батерије на измаку. Можда ће апликацији дозволити да сазна детаљне информације о томе које апликације користите."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"измена статистике о батерији"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Дозвољава апликацији да мења прикупљену статистику о батерији. Не користе је обичне апликације."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"преузимање статистике о функционисању апликације"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Дозвољава апликацији да преузима прикупљену статистику о функционисању апликације. Не користе је уобичајене апликације."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"измена статистике о функционисању апликације"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Дозвољава апликацији да измени прикупљену статистику о функционисању апликације. Не користе је уобичајене апликације."</string>
     <string name="permlab_backup" msgid="470013022865453920">"контрола резервне копије система и враћање почетних вредности"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index e975f68..9407d89 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Tillåter att en app läser de aktuella uppgifterna om låg batterianvändningsnivå. Appen kan tillåtas få reda på detaljerade uppgifter om vilka appar du använder."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"ändra batteristatistik"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Tillåter att appen ändrar samlad batteristatistik. Används inte av vanliga appar."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"hämta åtgärdsstatistik för appar"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Tillåter att appen hämtar samlad åtgärdsstatistik för appar. Används inte av vanliga appar."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"ändra appars åtgärdsstatistik"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Tillåter att appen ändrar samlad åtgärdsstatistik för appar. Används inte av vanliga appar."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrollera säkerhetskopiering och återställning av systemet"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index fff8a16..17a8c3e 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Inaruhusu programu kusoma data ya sasa ya matumizi ya kiwango cha chini cha betri. Huenda ikaruhusu kupata maelezo ya kina kuhusu programu unazozitumia."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"rekebisha takwimu za betri"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Inaruhusu programu kurekebisha takwimu za betri zilizokusanywa. Si ya kutumiwa na programu za kawaida."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"epua takwimu za oparesheni ya programu"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Inaruhusu programu kuepua takwimu za matumizi ya programu zilizokusanywa. Si ya kutumiwa na programu za kawaida."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"rekebisha takwimu za oparesheni ya programu"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Inaruhusu programu kurekebisha takwimu za matumizi ya programu zilizokusanywa. Si ya kutumiwa na programu za kawaida."</string>
     <string name="permlab_backup" msgid="470013022865453920">"Dhibiti kuhifadhi nakala na kurejesha kwa mfumo"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 96e03b1..7f3e7fe 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลการใช้แบตเตอรี่ที่มีพลังงานเหลือน้อยในปัจจุบัน โดยอาจอนุญาตให้แอปพลิเคชันค้นหาข้อมูลรายละเอียดว่าคุณใช้งานแอปพลิเคชันใดบ้าง"</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"แก้ไขสถิติของแบตเตอรี่"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"อนุญาตให้แอปพลิเคชันแก้ไขสถิติของแบตเตอรี่่ที่เก็บรวบรวมไว้ ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"เรียกคืนสถิติการทำงานของแอปพลิเคชัน"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"อนุญาตให้แอปพลิเคชันเรียกคืนสถิติการทำงานของแอปพลิเคชันที่เก็บรวบรวมไว้ ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"แก้ไขสถิติการทำงานของแอปพลิเคชัน"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"อนุญาตให้แอปพลิเคชันแก้ไขสถิติการทำงานของแอปพลิเคชันที่เก็บรวบรวมไว้ ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_backup" msgid="470013022865453920">"ควบคุมการสำรองและคืนค่า"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 95d8cf2..b0878af 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Binibigyang-daan ang application na basahin ang kasalukuyang data sa paggamit ng mababang antas ng baterya. Maaaring bigyang-daan ang application na malaman ang detalyadong impormasyon tungkol sa kung aling apps ang ginagamit mo."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"baguhin ang mga istatistika ng baterya"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Binibigyang-daan ang app na baguhin ang mga nakolektang istatistika ng baterya. Hindi para sa paggamit ng normal na apps."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"bawiin ang mga istatistika ng pagpapagana ng app"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Binibigyang-daan ang app na bawiin ang mga nakolektang istatistika ng pagpapagana ng application. Hindi para sa paggamit ng normal na apps."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"baguhin ang mga istatistika ng pagpapatakbo ng app"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Binibigyang-daan ang app na baguhin ang mga nakolektang istatistika ng pagpapatakbo ng application. Hindi para sa paggamit ng normal na apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrolin ang system backup at pagbawi"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 7308264..d8dc8ea 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Uygulamaya, mevcut pil kullanım verilerini alt düzeyde okuma izni verir. Uygulamanın hangi uygulamaları kullandığınızla ilgili ayrıntılı bilgi edinmesine olanak sağlayabilir."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"pil istatistiklerini değiştir"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Uygulamaya, toplanan pil kullanım istatistiklerini değiştirme izni verir. Normal uygulamaların kullanımına yönelik değildir."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"uygulama çalışma istatistiklerini al"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Uygulamaya, uygulama çalışma istatistiklerini alma izni verir. Normal uygulamaların kullanımına yönelik değildir."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"uygulama çalışma istatistiklerini değiştir"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Uygulamaya, uygulama çalışma istatistiklerini değiştirme izni verir. Normal uygulamaların kullanımına yönelik değildir."</string>
     <string name="permlab_backup" msgid="470013022865453920">"sistem yedeğini kontrol et ve geri yükle"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 17460f1..5fa13cc 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Дозволяє програмі зчитувати дані про поточний низький рівень споживання заряду акумулятора. Програма може отримувати докладну інформацію про те, якими програмами ви користуєтеся."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"змінювати статистику акумулятора"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Дозволяє програмі змінювати зібрану статистику акумулятора. Не для використання звичайними програмами."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"отримувати статистику роботи програми"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Дозволяє програмі отримувати зібрану статистику роботи програми. Не використовується звичайними програмами."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"змінювати статистику роботи програми"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Дозволяє програмі змінювати зібрану статистику роботи програми. Не використовується звичайними програмами."</string>
     <string name="permlab_backup" msgid="470013022865453920">"контр. резерв. копіюв. і відн. сист."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 148f4a8..9e34a8f 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Cho phép ứng dụng đọc dữ liệu sử dụng pin mức thấp hiện tại. Có thể cho phép ứng dụng biết thông tin chi tiết về ứng dụng bạn sử dụng."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"sửa đổi số liệu thống kê về pin"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Cho phép ứng dụng sửa đổi các số liệu thống kê về pin đã được thu thập. Không dành cho các ứng dụng thông thường."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"truy xuất số liệu thống kê hoạt động của ứng dụng"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Cho phép ứng dụng truy xuất số liệu thống kê hoạt động của ứng dụng đã thu thập. Không dành cho ứng dụng thông thường."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"sửa đổi số liệu thống kê hoạt động của ứng dụng"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Cho phép ứng dụng sửa đổi số liệu thống kê hoạt động của ứng dụng đã thu thập. Không dành cho ứng dụng thông thường."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kiểm soát sao lưu và khôi phục hệ thống"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index fa43c99..a1fda84 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"允许应用读取当前电量使用情况的基础数据,此权限可让应用了解关于您使用了哪些应用的详细信息。"</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"修改电池使用统计信息"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"允许该应用修改收集到的电池统计信息。普通应用不应使用此权限。"</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"检索应用操作统计信息"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"允许该应用检索收集到的应用操作统计信息。普通应用不应使用此权限。"</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"修改应用操作统计信息"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"允许该应用修改收集到的应用操作统计信息。普通应用不应使用此权限。"</string>
     <string name="permlab_backup" msgid="470013022865453920">"控制系统备份和还原"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 3bfed3c..9bb6b99 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -315,8 +315,10 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"允許應用程式讀取目前的低電量使用資料。應用程式可能藉此找到一些詳細資訊,例如您所使用的應用程式為何。"</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"修改電池使用統計資料"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"允許應用程式修改收集到的電池使用統計資料 (不建議一般應用程式使用)。"</string>
-    <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"修改應用程式作業統計資料"</string>
-    <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"允許應用程式修改收集到的應用程式作業統計資料 (不建議一般應用程式使用)。"</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"擷取應用程式作業統計資料"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"允許應用程式擷取收集到的應用程式作業統計資料 (不建議一般應用程式使用)。"</string>
+    <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"修改應用程式操作統計資料"</string>
+    <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"允許應用程式修改收集到的應用程式操作統計資料 (不建議一般應用程式使用)。"</string>
     <string name="permlab_backup" msgid="470013022865453920">"控制系統備份與還原"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"允許應用程式控制系統備份與還原機制 (不建議一般應用程式使用)。"</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"確認完整備份或還原作業"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 54be6ea..1d2e497 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -315,6 +315,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Ivumela uhlelo lokusebenza ukufunda idatha yokusebenza yebhethri leleveli ephansi yamanje. Ingavumela uhlelo lokusebenza ukuthola ulwazi lemininingwane mayelana nokuthi iziphi izinhlelo zokusebenza ozisebenzisayo."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"guqula izibalo zebhetri"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Ivumela uhlelo lokusebenza ukuthi luguqule izibalo zebhethri eziqoqiwe. Akwenzelwe ukuthi kusetshenziswe izinhlelo zokusebenza ezijwayelekile."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"thola izibalo zokusebenza kohlelo lokusebenza"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Ivumela uhlelo lokusebenza ukuthi lithole izibalo zokusebenza kohlelo lokusebenza. Akumele kusetshenziswe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"shintsha izinombolo zokusebenza zohlelo lokusebenza"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Ivumela uhlelo lokusebenza ukuthi lishintshe izinombolo zokusebenza kohlelo lokusebenza lokuqoqiwe. Akufanele kusetshenziswe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_backup" msgid="470013022865453920">"lawula ukusekela ngokulondoloza uhlelo bese ubuyisela esimweni"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index fa15324..dc921e6 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1541,6 +1541,7 @@
         <enum name="KEYCODE_YEN" value="216" />
         <enum name="KEYCODE_RO" value="217" />
         <enum name="KEYCODE_KANA" value="218" />
+        <enum name="KEYCODE_ASSIST" value="219" />
     </attr>
 
     <!-- ***************************************************************** -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7ef501f..fda554d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -277,8 +277,6 @@
     <!-- Boolean indicating whether the wifi chipset has dual frequency band support -->
     <bool translatable="false" name="config_wifi_dual_band_support">false</bool>
 
-    <!-- Boolean indicating whether the wifi chipset has p2p support -->
-    <bool translatable="false" name="config_wifi_p2p_support">false</bool>
     <!-- Device type information conforming to Annex B format in WiFi Direct specification.
          The default represents a dual-mode smartphone -->
     <string translatable="false" name="config_wifi_p2p_device_type">10-0050F204-5</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fa26089..7f0fc0b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -784,6 +784,12 @@
         another app.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_getTopActivityInfo">get current app info</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_getTopActivityInfo">Allows the holder to retrieve private information
+        about the current application in the foreground of the screen.</string>
+    
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_runSetActivityWatcher">monitor and control all app launching</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_runSetActivityWatcher">Allows the app to
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6db89d9..412d4b9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1113,6 +1113,7 @@
   <java-symbol type="layout" name="keyguard_multi_user_selector_widget" />
   <java-symbol type="layout" name="sms_short_code_confirmation_dialog" />
   <java-symbol type="layout" name="keyguard_add_widget" />
+  <java-symbol type="layout" name="action_bar_up_container" />
 
   <java-symbol type="anim" name="slide_in_child_bottom" />
   <java-symbol type="anim" name="slide_in_right" />
@@ -1337,7 +1338,6 @@
   <java-symbol type="id" name="sliding_layout" />
   <java-symbol type="id" name="keyguard_add_widget" />
   <java-symbol type="id" name="keyguard_add_widget_view" />
-  <java-symbol type="id" name="sliding_layout" />
   <java-symbol type="id" name="multi_pane_challenge" />
   <java-symbol type="id" name="keyguard_user_selector" />
   <java-symbol type="id" name="key_enter" />
diff --git a/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java b/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java
new file mode 100644
index 0000000..cb468bc
--- /dev/null
+++ b/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import junit.framework.TestCase;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * Tests for {@link LongSparseLongArray}.
+ */
+public class LongSparseLongArrayTest extends TestCase {
+    private static final String TAG = "LongSparseLongArrayTest";
+
+    public void testSimplePut() throws Exception {
+        final LongSparseLongArray array = new LongSparseLongArray(5);
+        for (int i = 0; i < 48; i++) {
+            final long value = 1 << i;
+            array.put(value, value);
+        }
+        for (int i = 0; i < 48; i++) {
+            final long value = 1 << i;
+            assertEquals(value, array.get(value, -1));
+            assertEquals(-1, array.get(-value, -1));
+        }
+    }
+
+    public void testSimplePutBackwards() throws Exception {
+        final LongSparseLongArray array = new LongSparseLongArray(5);
+        for (int i = 47; i >= 0; i--) {
+            final long value = 1 << i;
+            array.put(value, value);
+        }
+        for (int i = 0; i < 48; i++) {
+            final long value = 1 << i;
+            assertEquals(value, array.get(value, -1));
+            assertEquals(-1, array.get(-value, -1));
+        }
+    }
+
+    public void testMiddleInsert() throws Exception {
+        final LongSparseLongArray array = new LongSparseLongArray(5);
+        for (int i = 0; i < 48; i++) {
+            final long value = 1 << i;
+            array.put(value, value);
+        }
+        final long special = (1 << 24) + 5;
+        array.put(special, 1024);
+        for (int i = 0; i < 48; i++) {
+            final long value = 1 << i;
+            assertEquals(value, array.get(value, -1));
+            assertEquals(-1, array.get(-value, -1));
+        }
+        assertEquals(1024, array.get(special, -1));
+    }
+
+    public void testFuzz() throws Exception {
+        final Random r = new Random();
+
+        final HashMap<Long, Long> map = new HashMap<Long, Long>();
+        final LongSparseLongArray array = new LongSparseLongArray(r.nextInt(128));
+
+        for (int i = 0; i < 10240; i++) {
+            if (r.nextBoolean()) {
+                final long key = r.nextLong();
+                final long value = r.nextLong();
+                map.put(key, value);
+                array.put(key, value);
+            }
+            if (r.nextBoolean() && map.size() > 0) {
+                final int index = r.nextInt(map.size());
+                final long key = getKeyAtIndex(map, index);
+                map.remove(key);
+                array.delete(key);
+            }
+        }
+
+        Log.d(TAG, "verifying a map with " + map.size() + " entries");
+
+        for (Map.Entry<Long, Long> e : map.entrySet()) {
+            final long key = e.getKey();
+            final long value = e.getValue();
+            assertEquals(value, array.get(key));
+        }
+    }
+
+    private static <E> E getKeyAtIndex(Map<E, ?> map, int index) {
+        final Iterator<E> keys = map.keySet().iterator();
+        for (int i = 0; i < index; i++) {
+            keys.next();
+        }
+        return keys.next();
+    }
+}
diff --git a/graphics/java/android/renderscript/Matrix3f.java b/graphics/java/android/renderscript/Matrix3f.java
index 66f2c81..0bad7e0 100644
--- a/graphics/java/android/renderscript/Matrix3f.java
+++ b/graphics/java/android/renderscript/Matrix3f.java
@@ -138,7 +138,7 @@
         mMat[6] =  zx*nc + ys;
         mMat[1] =  xy*nc + zs;
         mMat[4] = y*y*nc +  c;
-        mMat[9] =  yz*nc - xs;
+        mMat[7] =  yz*nc - xs;
         mMat[2] =  zx*nc - ys;
         mMat[6] =  yz*nc + xs;
         mMat[8] = z*z*nc +  c;
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
index aabfcae..65d7b8f 100644
--- a/keystore/java/android/security/AndroidKeyStore.java
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -16,9 +16,8 @@
 
 package android.security;
 
-import org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPrivateKey;
 import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLKeyHolder;
 
 import android.util.Log;
 
@@ -210,10 +209,8 @@
         byte[] keyBytes = null;
 
         final String pkeyAlias;
-        if (key instanceof OpenSSLRSAPrivateKey) {
-            pkeyAlias = ((OpenSSLRSAPrivateKey) key).getPkeyAlias();
-        } else if (key instanceof OpenSSLDSAPrivateKey) {
-            pkeyAlias = ((OpenSSLDSAPrivateKey) key).getPkeyAlias();
+        if (key instanceof OpenSSLKeyHolder) {
+            pkeyAlias = ((OpenSSLKeyHolder) key).getOpenSSLKey().getAlias();
         } else {
             pkeyAlias = null;
         }
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 1d85b70..79dbfb0 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -54,6 +54,51 @@
     deleteTexture();
 }
 
+uint32_t Layer::computeIdealWidth(uint32_t layerWidth) {
+    return uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE);
+}
+
+uint32_t Layer::computeIdealHeight(uint32_t layerHeight) {
+    return uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE);
+}
+
+bool Layer::resize(const uint32_t width, const uint32_t height) {
+    uint32_t desiredWidth = computeIdealWidth(width);
+    uint32_t desiredHeight = computeIdealWidth(height);
+
+    if (desiredWidth <= getWidth() && desiredHeight <= getHeight()) {
+        return true;
+    }
+
+    uint32_t oldWidth = getWidth();
+    uint32_t oldHeight = getHeight();
+
+    setSize(desiredWidth, desiredHeight);
+
+    if (fbo) {
+        Caches::getInstance().activeTexture(0);
+        bindTexture();
+        allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
+
+        if (glGetError() != GL_NO_ERROR) {
+            setSize(oldWidth, oldHeight);
+            return false;
+        }
+    }
+
+    if (stencil) {
+        bindStencilRenderBuffer();
+        allocateStencilRenderBuffer();
+
+        if (glGetError() != GL_NO_ERROR) {
+            setSize(oldWidth, oldHeight);
+            return false;
+        }
+    }
+
+    return true;
+}
+
 void Layer::removeFbo(bool flush) {
     if (stencil) {
         // TODO: recycle & cache instead of simply deleting
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 9ef4894..a551b3f 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -48,6 +48,9 @@
     Layer(const uint32_t layerWidth, const uint32_t layerHeight);
     ~Layer();
 
+    static uint32_t computeIdealWidth(uint32_t layerWidth);
+    static uint32_t computeIdealHeight(uint32_t layerHeight);
+
     /**
      * Calling this method will remove (either by recycling or
      * destroying) the associated FBO, if present, and any render
@@ -91,6 +94,17 @@
         return texture.height;
     }
 
+    /**
+     * Resize the layer and its texture if needed.
+     *
+     * @param width The new width of the layer
+     * @param height The new height of the layer
+     *
+     * @return True if the layer was resized or nothing happened, false if
+     *         a failure occurred during the resizing operation
+     */
+    bool resize(const uint32_t width, const uint32_t height);
+
     void setSize(uint32_t width, uint32_t height) {
         texture.width = width;
         texture.height = height;
@@ -203,6 +217,12 @@
         }
     }
 
+    inline void bindStencilRenderBuffer() {
+        if (stencil) {
+            glBindRenderbuffer(GL_RENDERBUFFER, stencil);
+        }
+    }
+
     inline void generateTexture() {
         if (!texture.id) {
             glGenTextures(1, &texture.id);
@@ -229,7 +249,16 @@
 #if DEBUG_LAYERS
         ALOGD("  Allocate layer: %dx%d", getWidth(), getHeight());
 #endif
-        glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL);
+        if (texture.id) {
+            glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0,
+                    format, storage, NULL);
+        }
+    }
+
+    inline void allocateStencilRenderBuffer() {
+        if (stencil) {
+            glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWidth(), getHeight());
+        }
     }
 
     inline mat4& getTexTransform() {
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index cfc5b04..4278464 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -136,31 +136,6 @@
     }
 }
 
-bool LayerCache::resize(Layer* layer, const uint32_t width, const uint32_t height) {
-    // TODO: We should be smarter and see if we have a texture of the appropriate
-    //       size already in the cache, and reuse it instead of creating a new one
-
-    LayerEntry entry(width, height);
-    if (entry.mWidth <= layer->getWidth() && entry.mHeight <= layer->getHeight()) {
-        return true;
-    }
-
-    uint32_t oldWidth = layer->getWidth();
-    uint32_t oldHeight = layer->getHeight();
-
-    Caches::getInstance().activeTexture(0);
-    layer->bindTexture();
-    layer->setSize(entry.mWidth, entry.mHeight);
-    layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
-
-    if (glGetError() != GL_NO_ERROR) {
-        layer->setSize(oldWidth, oldHeight);
-        return false;
-    }
-
-    return true;
-}
-
 bool LayerCache::put(Layer* layer) {
     if (!layer->isCacheable()) return false;
 
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index fc2cd91..7720b42 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -72,17 +72,6 @@
      * Clears the cache. This causes all layers to be deleted.
      */
     void clear();
-    /**
-     * Resize the specified layer if needed.
-     *
-     * @param layer The layer to resize
-     * @param width The new width of the layer
-     * @param height The new height of the layer
-     *
-     * @return True if the layer was resized or nothing happened, false if
-     *         a failure occurred during the resizing operation
-     */
-    bool resize(Layer* layer, const uint32_t width, const uint32_t height);
 
     /**
      * Sets the maximum size of the cache in bytes.
@@ -108,8 +97,8 @@
         }
 
         LayerEntry(const uint32_t layerWidth, const uint32_t layerHeight): mLayer(NULL) {
-            mWidth = uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE);
-            mHeight = uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE);
+            mWidth = Layer::computeIdealWidth(layerWidth);
+            mHeight = Layer::computeIdealHeight(layerHeight);
         }
 
         LayerEntry(Layer* layer):
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index ba59bb39..61bedbb 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -264,7 +264,7 @@
     if (layer) {
         LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->getFbo(), width, height);
 
-        if (Caches::getInstance().layerCache.resize(layer, width, height)) {
+        if (layer->resize(width, height)) {
             layer->layer.set(0.0f, 0.0f, width, height);
             layer->texCoords.set(0.0f, height / float(layer->getHeight()),
                     width / float(layer->getWidth()), 0.0f);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index be34b40..f55bc9d 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1248,11 +1248,12 @@
         // TODO: See Layer::removeFbo(). The stencil renderbuffer should be cached
         GLuint buffer;
         glGenRenderbuffers(1, &buffer);
-        glBindRenderbuffer(GL_RENDERBUFFER, buffer);
-        glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8,
-                layer->getWidth(), layer->getHeight());
-        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer);
+
         layer->setStencilRenderBuffer(buffer);
+        layer->bindStencilRenderBuffer();
+        layer->allocateStencilRenderBuffer();
+
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer);
     }
 }
 
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 14fe6af..b85121e 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -49,7 +49,8 @@
     <uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" />
     <uses-permission android:name="android.permission.START_ANY_ACTIVITY" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
-
+    <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
+    
     <!-- WindowManager -->
     <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
diff --git a/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml
new file mode 100644
index 0000000..03ca729
--- /dev/null
+++ b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml
@@ -0,0 +1,322 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<com.android.systemui.statusbar.phone.NavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:background="#FF000000"
+    >
+
+    <FrameLayout android:id="@+id/rot0"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        >
+
+        <LinearLayout
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:orientation="horizontal"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:id="@+id/nav_buttons"
+            android:animateLayoutChanges="true"
+            >
+
+            <!-- navigation controls -->
+            <View
+                android:layout_width="40dp"
+                android:layout_height="match_parent"
+                android:layout_weight="0"
+                android:visibility="invisible"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
+                android:layout_width="@dimen/navigation_key_width"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_back"
+                systemui:keyCode="4"
+                android:layout_weight="0"
+                android:scaleType="center"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                android:contentDescription="@string/accessibility_back"
+                />
+            <View 
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
+                android:layout_width="@dimen/navigation_key_width"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_home"
+                systemui:keyCode="3"
+                systemui:keyRepeat="false"
+                android:layout_weight="0"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                android:contentDescription="@string/accessibility_home"
+                />
+            <View 
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
+                android:layout_width="@dimen/navigation_key_width"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_recent"
+                android:layout_weight="0"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                android:contentDescription="@string/accessibility_recent"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+                android:layout_width="@dimen/navigation_menu_key_width"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_menu"
+                systemui:keyCode="82"
+                android:layout_weight="0"
+                android:visibility="invisible"
+                android:contentDescription="@string/accessibility_menu"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                />
+        </LinearLayout>
+
+        <!-- lights out layout to match exactly -->
+        <LinearLayout
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:orientation="horizontal"
+            android:id="@+id/lights_out"
+            android:visibility="gone"
+            >
+            <ImageView
+                android:layout_width="80dp"
+                android:layout_height="match_parent"
+                android:layout_marginStart="40dp"
+                android:src="@drawable/ic_sysbar_lights_out_dot_small"
+                android:scaleType="center"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <ImageView
+                android:layout_width="80dp"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_lights_out_dot_large"
+                android:scaleType="center"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <ImageView
+                android:layout_width="80dp"
+                android:layout_marginEnd="40dp"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_lights_out_dot_small"
+                android:scaleType="center"
+                android:layout_weight="0"
+                />
+        </LinearLayout>
+
+        <com.android.systemui.statusbar.policy.KeyButtonView
+            android:layout_width="80dp"
+            android:id="@+id/search_light"
+            android:layout_height="match_parent"
+            android:layout_gravity="center_horizontal"
+            android:src="@drawable/search_light"
+            android:scaleType="center"
+            android:visibility="gone"
+            />
+
+        <com.android.systemui.statusbar.policy.DeadZone
+            android:id="@+id/deadzone"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            systemui:minSize="@dimen/navigation_bar_deadzone_size"
+            systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+            systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+            systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+            systemui:orientation="horizontal"
+            android:layout_gravity="top"
+            />
+    </FrameLayout>
+
+    <FrameLayout android:id="@+id/rot90"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:visibility="gone"
+        android:paddingTop="0dp"
+        >
+
+        <LinearLayout 
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:orientation="vertical"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:id="@+id/nav_buttons"
+            android:animateLayoutChanges="true"
+            >
+            
+            <!-- navigation controls -->
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+                android:layout_height="40dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_menu_land"
+                systemui:keyCode="82"
+                android:layout_weight="0"
+                android:visibility="invisible"
+                android:contentDescription="@string/accessibility_menu"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_back_land"
+                android:scaleType="center"
+                systemui:keyCode="4"
+                android:layout_weight="0"
+                android:contentDescription="@string/accessibility_back"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+                />
+            <View
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_home_land"
+                systemui:keyCode="3"
+                systemui:keyRepeat="false"
+                android:layout_weight="0"
+                android:contentDescription="@string/accessibility_home"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+                />
+            <View 
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_recent_land"
+                android:layout_weight="0"
+                android:contentDescription="@string/accessibility_recent"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+                />
+            <View
+                android:layout_height="40dp"
+                android:layout_width="match_parent"
+                android:layout_weight="0"
+                android:visibility="invisible"
+                />
+        </LinearLayout>
+
+        <!-- lights out layout to match exactly -->
+        <LinearLayout 
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:orientation="vertical"
+            android:id="@+id/lights_out"
+            android:visibility="gone"
+            >
+            <ImageView
+                android:layout_height="80dp"
+                android:layout_marginTop="40dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_lights_out_dot_small"
+                android:scaleType="center"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <ImageView
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_lights_out_dot_large"
+                android:scaleType="center"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <ImageView
+                android:layout_height="80dp"
+                android:layout_marginBottom="40dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_lights_out_dot_small"
+                android:scaleType="center"
+                android:layout_weight="0"
+                />
+        </LinearLayout>
+
+        <com.android.systemui.statusbar.policy.KeyButtonView
+            android:id="@+id/search_light"
+            android:layout_height="80dp"
+            android:layout_width="match_parent"
+            android:layout_gravity="center_vertical"
+            android:src="@drawable/search_light"
+            android:scaleType="center"
+            android:visibility="gone"
+            />
+
+        <com.android.systemui.statusbar.policy.DeadZone
+            android:id="@+id/deadzone"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            systemui:minSize="@dimen/navigation_bar_deadzone_size"
+            systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+            systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+            systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+            systemui:orientation="vertical"
+            android:layout_gravity="top"
+            />
+    </FrameLayout>
+
+    <!-- not used -->
+    <View android:id="@+id/rot270"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:visibility="gone"
+        />
+
+</com.android.systemui.statusbar.phone.NavigationBarView>
diff --git a/packages/SystemUI/res/layout/status_bar_recent_item.xml b/packages/SystemUI/res/layout/status_bar_recent_item.xml
index 7ce3a09..6290bb3 100644
--- a/packages/SystemUI/res/layout/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout/status_bar_recent_item.xml
@@ -48,6 +48,7 @@
             android:ellipsize="marquee"
             android:textColor="@color/status_bar_recents_app_label_color"
             android:importantForAccessibility="no"
+            android:textAlignment="viewStart"
         />
         <FrameLayout android:id="@+id/app_thumbnail"
             android:layout_width="wrap_content"
@@ -101,6 +102,7 @@
             android:layout_marginTop="3dip"
             android:singleLine="true"
             android:ellipsize="marquee"
+            android:textAlignment="viewStart"
         />
 
     </RelativeLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index c0a6f56..1f29990 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -103,7 +103,7 @@
         } else {
             // Otherwise, keyguard isn't showing so launch it from here.
             Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                    .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                    .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
             if (intent == null) return;
 
             try {
@@ -180,7 +180,7 @@
 
     private void maybeSwapSearchIcon() {
         Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                .getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
         if (intent != null) {
             ComponentName component = intent.getComponent();
             if (component == null || !mGlowPadView.replaceTargetDrawablesIfPresent(component,
@@ -329,6 +329,6 @@
 
     public boolean isAssistantAvailable() {
         return ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+                .getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 17b0b50..280b368 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -72,6 +72,13 @@
     Runnable finisher;
     int iconSize;
     int result;
+
+    void clearImage() {
+        context = null;
+        image = null;
+        imageUri = null;
+        iconSize = 0;
+    }
 }
 
 /**
@@ -165,6 +172,10 @@
     @Override
     protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
         if (params.length != 1) return null;
+        if (isCancelled()) {
+            params[0].clearImage();
+            return null;
+        }
 
         // By default, AsyncTask sets the worker thread to have background thread priority, so bump
         // it back up so that we save a little quicker.
@@ -225,8 +236,7 @@
         } catch (Exception e) {
             // IOException/UnsupportedOperationException may be thrown if external storage is not
             // mounted
-            params[0].imageUri = null;
-            params[0].image = null;
+            params[0].clearImage();
             params[0].result = 1;
         }
 
@@ -240,6 +250,12 @@
 
     @Override
     protected void onPostExecute(SaveImageInBackgroundData params) {
+        if (isCancelled()) {
+            params.finisher.run();
+            params.clearImage();
+            return;
+        }
+
         if (params.result > 0) {
             // Show a message that we've failed to save the image to disk
             GlobalScreenshot.notifyScreenshotError(params.context, mNotificationManager);
@@ -308,6 +324,8 @@
     private float mBgPadding;
     private float mBgPaddingScale;
 
+    private AsyncTask<SaveImageInBackgroundData, Void, SaveImageInBackgroundData> mSaveInBgTask;
+
     private MediaActionSound mCameraSound;
 
 
@@ -374,7 +392,10 @@
         data.image = mScreenBitmap;
         data.iconSize = mNotificationIconSize;
         data.finisher = finisher;
-        new SaveImageInBackgroundTask(mContext, data, mNotificationManager,
+        if (mSaveInBgTask != null) {
+            mSaveInBgTask.cancel(false);
+        }
+        mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data, mNotificationManager,
                 SCREENSHOT_NOTIFICATION_ID).execute(data);
     }
 
@@ -455,6 +476,7 @@
         // Setup the animation with the screenshot just taken
         if (mScreenshotAnimation != null) {
             mScreenshotAnimation.end();
+            mScreenshotAnimation.removeAllListeners();
         }
 
         mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index b5cbdd1..35ff3d6 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2206,7 +2206,7 @@
     private void launchAssistAction() {
         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
         Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
         if (intent != null) {
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                     | Intent.FLAG_ACTIVITY_SINGLE_TOP
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
index 217e5d7..27d808b 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -1567,7 +1567,7 @@
 
     public void showAssistant() {
         final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-          .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+          .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
 
         if (intent == null) return;
 
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
index 76cbbd5..6859042 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
@@ -61,7 +61,7 @@
                 case com.android.internal.R.drawable.ic_action_assist_generic:
                     Intent assistIntent =
                             ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                            .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                            .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
                     if (assistIntent != null) {
                         mActivityLauncher.launchActivity(assistIntent, false, true, null, null);
                     } else {
@@ -195,7 +195,7 @@
                 currentUserHandle);
         boolean searchActionAvailable =
                 ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+                .getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
         mCameraDisabled = cameraDisabledByAdmin || disabledBySimState || !cameraTargetPresent
                 || !currentUserSetup;
         mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent
@@ -207,7 +207,7 @@
         // Update the search icon with drawable from the search .apk
         if (!mSearchDisabled) {
             Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                    .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                    .getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
             if (intent != null) {
                 // XXX Hack. We need to substitute the icon here but haven't formalized
                 // the public API. The "_google" metadata will be going away, so
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
index fef0613..8e10528 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -1428,6 +1428,6 @@
 
     private boolean isAssistantAvailable() {
         return mSearchManager != null
-                && mSearchManager.getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+                && mSearchManager.getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
     }
 }
diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java
index 1712806..bf2a5ae 100644
--- a/services/java/com/android/server/AppOpsService.java
+++ b/services/java/com/android/server/AppOpsService.java
@@ -38,6 +38,7 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.util.AtomicFile;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -93,12 +94,15 @@
 
     final static class Op {
         public final int op;
+        public int mode;
         public int duration;
         public long time;
+        public long rejectTime;
         public int nesting;
 
         public Op(int _op) {
             op = _op;
+            mode = AppOpsManager.MODE_ALLOWED;
         }
     }
 
@@ -127,6 +131,30 @@
         }
     }
 
+    private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) {
+        ArrayList<AppOpsManager.OpEntry> resOps = null;
+        if (ops == null) {
+            resOps = new ArrayList<AppOpsManager.OpEntry>();
+            for (int j=0; j<pkgOps.size(); j++) {
+                Op curOp = pkgOps.valueAt(j);
+                resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
+                        curOp.rejectTime, curOp.duration));
+            }
+        } else {
+            for (int j=0; j<ops.length; j++) {
+                Op curOp = pkgOps.get(ops[j]);
+                if (curOp != null) {
+                    if (resOps == null) {
+                        resOps = new ArrayList<AppOpsManager.OpEntry>();
+                    }
+                    resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
+                            curOp.rejectTime, curOp.duration));
+                }
+            }
+        }
+        return resOps;
+    }
+
     @Override
     public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
@@ -136,26 +164,7 @@
             for (int i=0; i<mUidOps.size(); i++) {
                 HashMap<String, Ops> packages = mUidOps.valueAt(i);
                 for (Ops pkgOps : packages.values()) {
-                    ArrayList<AppOpsManager.OpEntry> resOps = null;
-                    if (ops == null) {
-                        resOps = new ArrayList<AppOpsManager.OpEntry>();
-                        for (int j=0; j<pkgOps.size(); j++) {
-                            Op curOp = pkgOps.valueAt(j);
-                            resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.time,
-                                    curOp.duration));
-                        }
-                    } else {
-                        for (int j=0; j<ops.length; j++) {
-                            Op curOp = pkgOps.get(ops[j]);
-                            if (curOp != null) {
-                                if (resOps == null) {
-                                    resOps = new ArrayList<AppOpsManager.OpEntry>();
-                                }
-                                resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.time,
-                                        curOp.duration));
-                            }
-                        }
-                    }
+                    ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
                     if (resOps != null) {
                         if (res == null) {
                             res = new ArrayList<AppOpsManager.PackageOps>();
@@ -171,6 +180,42 @@
     }
 
     @Override
+    public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName,
+            int[] ops) {
+        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
+                Binder.getCallingPid(), Binder.getCallingUid(), null);
+        synchronized (this) {
+            Ops pkgOps = getOpsLocked(uid, packageName, false);
+            if (pkgOps == null) {
+                return null;
+            }
+            ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
+            if (resOps == null) {
+                return null;
+            }
+            ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
+            AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
+                    pkgOps.packageName, pkgOps.uid, resOps);
+            res.add(resPackage);
+            return res;
+        }
+    }
+
+    @Override
+    public void setMode(int code, int uid, String packageName, int mode) {
+        uid = handleIncomingUid(uid);
+        synchronized (this) {
+            Op op = getOpLocked(code, uid, packageName, true);
+            if (op != null) {
+                if (op.mode != mode) {
+                    op.mode = mode;
+                    scheduleWriteNowLocked();
+                }
+            }
+        }
+    }
+
+    @Override
     public int checkOperation(int code, int uid, String packageName) {
         uid = handleIncomingUid(uid);
         synchronized (this) {
@@ -178,8 +223,8 @@
             if (op == null) {
                 return AppOpsManager.MODE_ALLOWED;
             }
+            return op.mode;
         }
-        return AppOpsManager.MODE_ALLOWED;
     }
 
     @Override
@@ -188,16 +233,26 @@
         synchronized (this) {
             Op op = getOpLocked(code, uid, packageName, true);
             if (op == null) {
+                if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
+                        + " package " + packageName);
                 return AppOpsManager.MODE_IGNORED;
             }
             if (op.duration == -1) {
                 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
                         + " code " + code + " time=" + op.time + " duration=" + op.duration);
             }
-            op.time = System.currentTimeMillis();
             op.duration = 0;
+            if (op.mode != AppOpsManager.MODE_ALLOWED) {
+                if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " + code
+                        + " uid " + uid + " package " + packageName);
+                op.rejectTime = System.currentTimeMillis();
+                return op.mode;
+            }
+            if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
+                    + " package " + packageName);
+            op.time = System.currentTimeMillis();
+            return AppOpsManager.MODE_ALLOWED;
         }
-        return AppOpsManager.MODE_ALLOWED;
     }
 
     @Override
@@ -206,15 +261,25 @@
         synchronized (this) {
             Op op = getOpLocked(code, uid, packageName, true);
             if (op == null) {
+                if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
+                        + " package " + packageName);
                 return AppOpsManager.MODE_IGNORED;
             }
+            if (op.mode != AppOpsManager.MODE_ALLOWED) {
+                if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code " + code
+                        + " uid " + uid + " package " + packageName);
+                op.rejectTime = System.currentTimeMillis();
+                return op.mode;
+            }
+            if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
+                    + " package " + packageName);
             if (op.nesting == 0) {
                 op.time = System.currentTimeMillis();
                 op.duration = -1;
             }
             op.nesting++;
+            return AppOpsManager.MODE_ALLOWED;
         }
-        return AppOpsManager.MODE_ALLOWED;
     }
 
     @Override
@@ -252,7 +317,7 @@
         return uid;
     }
 
-    private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
+    private Ops getOpsLocked(int uid, String packageName, boolean edit) {
         HashMap<String, Ops> pkgOps = mUidOps.get(uid);
         if (pkgOps == null) {
             if (!edit) {
@@ -289,6 +354,29 @@
             ops = new Ops(packageName, uid);
             pkgOps.put(packageName, ops);
         }
+        return ops;
+    }
+
+    private void scheduleWriteLocked() {
+        if (!mWriteScheduled) {
+            mWriteScheduled = true;
+            mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
+        }
+    }
+
+    private void scheduleWriteNowLocked() {
+        if (!mWriteScheduled) {
+            mWriteScheduled = true;
+        }
+        mHandler.removeCallbacks(mWriteRunner);
+        mHandler.post(mWriteRunner);
+    }
+
+    private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
+        Ops ops = getOpsLocked(uid, packageName, edit);
+        if (ops == null) {
+            return null;
+        }
         Op op = ops.get(code);
         if (op == null) {
             if (!edit) {
@@ -297,9 +385,8 @@
             op = new Op(code);
             ops.put(code, op);
         }
-        if (edit && !mWriteScheduled) {
-            mWriteScheduled = true;
-            mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
+        if (edit) {
+            scheduleWriteLocked();
         }
         return op;
     }
@@ -406,8 +493,22 @@
             String tagName = parser.getName();
             if (tagName.equals("op")) {
                 Op op = new Op(Integer.parseInt(parser.getAttributeValue(null, "n")));
-                op.time = Long.parseLong(parser.getAttributeValue(null, "t"));
-                op.duration = Integer.parseInt(parser.getAttributeValue(null, "d"));
+                String mode = parser.getAttributeValue(null, "m");
+                if (mode != null) {
+                    op.mode = Integer.parseInt(mode);
+                }
+                String time = parser.getAttributeValue(null, "t");
+                if (time != null) {
+                    op.time = Long.parseLong(time);
+                }
+                time = parser.getAttributeValue(null, "r");
+                if (time != null) {
+                    op.rejectTime = Long.parseLong(time);
+                }
+                String dur = parser.getAttributeValue(null, "d");
+                if (dur != null) {
+                    op.duration = Integer.parseInt(dur);
+                }
                 HashMap<String, Ops> pkgOps = mUidOps.get(uid);
                 if (pkgOps == null) {
                     pkgOps = new HashMap<String, Ops>();
@@ -464,8 +565,21 @@
                             AppOpsManager.OpEntry op = ops.get(j);
                             out.startTag(null, "op");
                             out.attribute(null, "n", Integer.toString(op.getOp()));
-                            out.attribute(null, "t", Long.toString(op.getTime()));
-                            out.attribute(null, "d", Integer.toString(op.getDuration()));
+                            if (op.getMode() != AppOpsManager.MODE_ALLOWED) {
+                                out.attribute(null, "m", Integer.toString(op.getMode()));
+                            }
+                            long time = op.getTime();
+                            if (time != 0) {
+                                out.attribute(null, "t", Long.toString(time));
+                            }
+                            time = op.getRejectTime();
+                            if (time != 0) {
+                                out.attribute(null, "r", Long.toString(time));
+                            }
+                            int dur = op.getDuration();
+                            if (dur != 0) {
+                                out.attribute(null, "d", Integer.toString(dur));
+                            }
                             out.endTag(null, "op");
                         }
                         out.endTag(null, "uid");
@@ -497,6 +611,7 @@
 
         synchronized (this) {
             pw.println("Current AppOps Service state:");
+            final long now = System.currentTimeMillis();
             for (int i=0; i<mUidOps.size(); i++) {
                 pw.print("  Uid "); UserHandle.formatUid(pw, mUidOps.keyAt(i)); pw.println(":");
                 HashMap<String, Ops> pkgOps = mUidOps.valueAt(i);
@@ -504,10 +619,16 @@
                     pw.print("    Package "); pw.print(ops.packageName); pw.println(":");
                     for (int j=0; j<ops.size(); j++) {
                         Op op = ops.valueAt(j);
-                        pw.print("      "); pw.print(AppOpsManager.opToString(op.op));
-                        pw.print(": time=");
-                        TimeUtils.formatDuration(System.currentTimeMillis()-op.time, pw);
-                        pw.print(" ago");
+                        pw.print("      "); pw.print(AppOpsManager.opToName(op.op));
+                        pw.print(": mode="); pw.print(op.mode);
+                        if (op.time != 0) {
+                            pw.print("; time="); TimeUtils.formatDuration(now-op.time, pw);
+                            pw.print(" ago");
+                        }
+                        if (op.rejectTime != 0) {
+                            pw.print("; rejectTime="); TimeUtils.formatDuration(now-op.rejectTime, pw);
+                            pw.print(" ago");
+                        }
                         if (op.duration == -1) {
                             pw.println(" (running)");
                         } else {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 5aba7ec..7cfa8c2 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -183,7 +183,7 @@
      * A per Net list of the PID's that requested access to the net
      * used both as a refcount and for per-PID DNS selection
      */
-    private List<Integer> mNetRequestersPids[];
+    private List mNetRequestersPids[];
 
     // priority order of the nettrackers
     // (excluding dynamically set mNetworkPreference)
@@ -199,6 +199,7 @@
     private int mDefaultConnectionSequence = 0;
 
     private Object mDnsLock = new Object();
+    private int mNumDnsEntries;
     private boolean mDnsOverridden = false;
 
     private boolean mTestMode;
@@ -506,14 +507,15 @@
             }
         }
 
-        mNetRequestersPids =
-                (List<Integer> [])new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
+        mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
         for (int i : mPriorityList) {
-            mNetRequestersPids[i] = new ArrayList<Integer>();
+            mNetRequestersPids[i] = new ArrayList();
         }
 
         mFeatureUsers = new ArrayList<FeatureUser>();
 
+        mNumDnsEntries = 0;
+
         mTestMode = SystemProperties.get("cm.test.mode").equals("true")
                 && SystemProperties.get("ro.build.type").equals("eng");
 
@@ -1314,7 +1316,6 @@
                 Integer currentPid = new Integer(pid);
                 mNetRequestersPids[usedNetworkType].remove(currentPid);
                 reassessPidDns(pid, true);
-                flushVmDnsCache();
                 if (mNetRequestersPids[usedNetworkType].size() != 0) {
                     if (VDBG) {
                         log("stopUsingNetworkFeature: net " + networkType + ": " + feature +
@@ -1696,8 +1697,9 @@
          * in accordance with network preference policies.
          */
         if (!mNetConfigs[prevNetType].isDefault()) {
-            List<Integer> pids = mNetRequestersPids[prevNetType];
-            for (Integer pid : pids) {
+            List pids = mNetRequestersPids[prevNetType];
+            for (int i = 0; i<pids.size(); i++) {
+                Integer pid = (Integer)pids.get(i);
                 // will remove them because the net's no longer connected
                 // need to do this now as only now do we know the pids and
                 // can properly null things that are no longer referenced.
@@ -2259,7 +2261,6 @@
                         }
                     }
                     if (resetDns) {
-                        flushVmDnsCache();
                         if (VDBG) log("resetting DNS cache for " + iface);
                         try {
                             mNetd.flushInterfaceDnsCache(iface);
@@ -2426,10 +2427,9 @@
      * on the highest priority active net which this process requested.
      * If there aren't any, clear it out
      */
-    private void reassessPidDns(int pid, boolean doBump)
+    private void reassessPidDns(int myPid, boolean doBump)
     {
-        if (VDBG) log("reassessPidDns for pid " + pid);
-        Integer myPid = new Integer(pid);
+        if (VDBG) log("reassessPidDns for pid " + myPid);
         for(int i : mPriorityList) {
             if (mNetConfigs[i].isDefault()) {
                 continue;
@@ -2439,25 +2439,61 @@
                     !nt.isTeardownRequested()) {
                 LinkProperties p = nt.getLinkProperties();
                 if (p == null) continue;
-                if (mNetRequestersPids[i].contains(myPid)) {
-                    try {
-                        mNetd.setDnsIfaceForPid(p.getInterfaceName(), pid);
-                    } catch (Exception e) {
-                        Slog.e(TAG, "exception reasseses pid dns: " + e);
+                List pids = mNetRequestersPids[i];
+                for (int j=0; j<pids.size(); j++) {
+                    Integer pid = (Integer)pids.get(j);
+                    if (pid.intValue() == myPid) {
+                        Collection<InetAddress> dnses = p.getDnses();
+                        writePidDns(dnses, myPid);
+                        if (doBump) {
+                            bumpDns();
+                        }
+                        return;
                     }
-                    return;
                 }
            }
         }
         // nothing found - delete
-        try {
-            mNetd.clearDnsIfaceForPid(pid);
-        } catch (Exception e) {
-            Slog.e(TAG, "exception clear interface from pid: " + e);
+        for (int i = 1; ; i++) {
+            String prop = "net.dns" + i + "." + myPid;
+            if (SystemProperties.get(prop).length() == 0) {
+                if (doBump) {
+                    bumpDns();
+                }
+                return;
+            }
+            SystemProperties.set(prop, "");
         }
     }
 
-    private void flushVmDnsCache() {
+    // return true if results in a change
+    private boolean writePidDns(Collection <InetAddress> dnses, int pid) {
+        int j = 1;
+        boolean changed = false;
+        for (InetAddress dns : dnses) {
+            String dnsString = dns.getHostAddress();
+            if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
+                changed = true;
+                SystemProperties.set("net.dns" + j + "." + pid, dns.getHostAddress());
+            }
+            j++;
+        }
+        return changed;
+    }
+
+    private void bumpDns() {
+        /*
+         * Bump the property that tells the name resolver library to reread
+         * the DNS server list from the properties.
+         */
+        String propVal = SystemProperties.get("net.dnschange");
+        int n = 0;
+        if (propVal.length() != 0) {
+            try {
+                n = Integer.parseInt(propVal);
+            } catch (NumberFormatException e) {}
+        }
+        SystemProperties.set("net.dnschange", "" + (n+1));
         /*
          * Tell the VMs to toss their DNS caches
          */
@@ -2476,23 +2512,56 @@
     }
 
     // Caller must grab mDnsLock.
-    private void updateDns(String network, String iface,
+    private boolean updateDns(String network, String iface,
             Collection<InetAddress> dnses, String domains) {
+        boolean changed = false;
         int last = 0;
         if (dnses.size() == 0 && mDefaultDns != null) {
-            dnses = new ArrayList();
-            dnses.add(mDefaultDns);
-            if (DBG) {
-                loge("no dns provided for " + network + " - using " + mDefaultDns.getHostAddress());
+            ++last;
+            String value = mDefaultDns.getHostAddress();
+            if (!value.equals(SystemProperties.get("net.dns1"))) {
+                if (DBG) {
+                    loge("no dns provided for " + network + " - using " + value);
+                }
+                changed = true;
+                SystemProperties.set("net.dns1", value);
+            }
+        } else {
+            for (InetAddress dns : dnses) {
+                ++last;
+                String key = "net.dns" + last;
+                String value = dns.getHostAddress();
+                if (!changed && value.equals(SystemProperties.get(key))) {
+                    continue;
+                }
+                if (VDBG) {
+                    log("adding dns " + value + " for " + network);
+                }
+                changed = true;
+                SystemProperties.set(key, value);
             }
         }
-
-        try {
-            mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses), domains);
-            mNetd.setDefaultInterfaceForDns(iface);
-        } catch (Exception e) {
-            if (DBG) loge("exception setting default dns interface: " + e);
+        for (int i = last + 1; i <= mNumDnsEntries; ++i) {
+            String key = "net.dns" + i;
+            if (VDBG) log("erasing " + key);
+            changed = true;
+            SystemProperties.set(key, "");
         }
+        mNumDnsEntries = last;
+        if (SystemProperties.get("net.dns.search").equals(domains) == false) {
+            SystemProperties.set("net.dns.search", domains);
+            changed = true;
+        }
+
+        if (changed) {
+            try {
+                mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses), domains);
+                mNetd.setDefaultInterfaceForDns(iface);
+            } catch (Exception e) {
+                if (DBG) loge("exception setting default dns interface: " + e);
+            }
+        }
+        return changed;
     }
 
     private void handleDnsConfigurationChange(int netType) {
@@ -2502,11 +2571,12 @@
             LinkProperties p = nt.getLinkProperties();
             if (p == null) return;
             Collection<InetAddress> dnses = p.getDnses();
+            boolean changed = false;
             if (mNetConfigs[netType].isDefault()) {
                 String network = nt.getNetworkInfo().getTypeName();
                 synchronized (mDnsLock) {
                     if (!mDnsOverridden) {
-                        updateDns(network, p.getInterfaceName(), dnses, p.getDomains());
+                        changed = updateDns(network, p.getInterfaceName(), dnses, p.getDomains());
                     }
                 }
             } else {
@@ -2517,16 +2587,13 @@
                     if (DBG) loge("exception setting dns servers: " + e);
                 }
                 // set per-pid dns for attached secondary nets
-                List<Integer> pids = mNetRequestersPids[netType];
-                for (Integer pid : pids) {
-                    try {
-                        mNetd.setDnsIfaceForPid(p.getInterfaceName(), pid);
-                    } catch (Exception e) {
-                        Slog.e(TAG, "exception setting interface for pid: " + e);
-                    }
+                List pids = mNetRequestersPids[netType];
+                for (int y=0; y< pids.size(); y++) {
+                    Integer pid = (Integer)pids.get(y);
+                    changed = writePidDns(dnses, pid.intValue());
                 }
             }
-            flushVmDnsCache();
+            if (changed) bumpDns();
         }
     }
 
@@ -2585,7 +2652,7 @@
         pw.increaseIndent();
         for (int net : mPriorityList) {
             String pidString = net + ": ";
-            for (Integer pid : mNetRequestersPids[net]) {
+            for (Object pid : mNetRequestersPids[net]) {
                 pidString = pidString + pid.toString() + ", ";
             }
             pw.println(pidString);
@@ -3287,10 +3354,14 @@
             String domains = buffer.toString().trim();
 
             // Apply DNS changes.
+            boolean changed = false;
             synchronized (mDnsLock) {
-                updateDns("VPN", "VPN", addresses, domains);
+                changed = updateDns("VPN", "VPN", addresses, domains);
                 mDnsOverridden = true;
             }
+            if (changed) {
+                bumpDns();
+            }
 
             // Temporarily disable the default proxy.
             synchronized (mDefaultProxyLock) {
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 593b9bf..0f14265 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -382,6 +382,8 @@
     private boolean mInputBoundToKeyguard;
 
     class SettingsObserver extends ContentObserver {
+        String mLastEnabled = "";
+
         SettingsObserver(Handler handler) {
             super(handler);
             ContentResolver resolver = mContext.getContentResolver();
@@ -395,7 +397,13 @@
 
         @Override public void onChange(boolean selfChange) {
             synchronized (mMethodMap) {
-                updateFromSettingsLocked();
+                boolean enabledChanged = false;
+                String newEnabled = mSettings.getEnabledInputMethodsStr();
+                if (!mLastEnabled.equals(newEnabled)) {
+                    mLastEnabled = newEnabled;
+                    enabledChanged = true;
+                }
+                updateFromSettingsLocked(enabledChanged);
             }
         }
     }
@@ -539,7 +547,7 @@
                 }
 
                 if (changed) {
-                    updateFromSettingsLocked();
+                    updateFromSettingsLocked(false);
                 }
             }
         }
@@ -674,7 +682,7 @@
         }
 
         mSettingsObserver = new SettingsObserver(mHandler);
-        updateFromSettingsLocked();
+        updateFromSettingsLocked(true);
 
         // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME
         // according to the new system locale.
@@ -748,7 +756,7 @@
                 // If the locale is changed, needs to reset the default ime
                 resetDefaultImeLocked(mContext);
             }
-            updateFromSettingsLocked();
+            updateFromSettingsLocked(true);
             mLastSystemLocale = newLocale;
             if (!updateOnlyWhenLocaleChanged) {
                 try {
@@ -1533,7 +1541,27 @@
         return false;
     }
 
-    void updateFromSettingsLocked() {
+    void updateFromSettingsLocked(boolean enabledMayChange) {
+        if (enabledMayChange) {
+            List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
+            for (int i=0; i<enabled.size(); i++) {
+                // We allow the user to select "disabled until used" apps, so if they
+                // are enabling one of those here we now need to make it enabled.
+                InputMethodInfo imm = enabled.get(i);
+                try {
+                    ApplicationInfo ai = mIPackageManager.getApplicationInfo(imm.getPackageName(),
+                            PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
+                            mSettings.getCurrentUserId());
+                    if (ai.enabledSetting
+                            == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+                        mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(),
+                                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
+                                PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId());
+                    }
+                } catch (RemoteException e) {
+                }
+            }
+        }
         // We are assuming that whoever is changing DEFAULT_INPUT_METHOD and
         // ENABLED_INPUT_METHODS is taking care of keeping them correctly in
         // sync, so we will never have a DEFAULT_INPUT_METHOD that is not
@@ -2383,7 +2411,8 @@
 
         final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
                 new Intent(InputMethod.SERVICE_INTERFACE),
-                PackageManager.GET_META_DATA, mSettings.getCurrentUserId());
+                PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
+                mSettings.getCurrentUserId());
 
         final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
                 mFileManager.getAllAdditionalInputMethodSubtypes();
@@ -2429,7 +2458,7 @@
             if (!map.containsKey(defaultImiId)) {
                 Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
                 if (chooseNewDefaultIMELocked()) {
-                    updateFromSettingsLocked();
+                    updateFromSettingsLocked(true);
                 }
             } else {
                 // Double check that the default IME is certainly enabled.
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 7218a28..9606cf1 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -529,9 +529,6 @@
         }
 
         public boolean callLocationChangedLocked(Location location) {
-            if (!reportLocationAccessNoThrow(mUid, mPackageName, mAllowedResolutionLevel)) {
-                return true;
-            }
             if (mListener != null) {
                 try {
                     synchronized (this) {
@@ -802,14 +799,20 @@
         }
     }
 
-    boolean reportLocationAccessNoThrow(int uid, String packageName, int allowedResolutionLevel) {
-        int op;
+    public static int resolutionLevelToOp(int allowedResolutionLevel) {
         if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
             if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
-                op = AppOpsManager.OP_COARSE_LOCATION;
+                return AppOpsManager.OP_COARSE_LOCATION;
             } else {
-                op = AppOpsManager.OP_FINE_LOCATION;
+                return AppOpsManager.OP_FINE_LOCATION;
             }
+        }
+        return -1;
+    }
+
+    boolean reportLocationAccessNoThrow(int uid, String packageName, int allowedResolutionLevel) {
+        int op = resolutionLevelToOp(allowedResolutionLevel);
+        if (op >= 0) {
             if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
@@ -818,13 +821,8 @@
     }
 
     boolean checkLocationAccess(int uid, String packageName, int allowedResolutionLevel) {
-        int op;
-        if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
-            if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
-                op = AppOpsManager.OP_COARSE_LOCATION;
-            } else {
-                op = AppOpsManager.OP_FINE_LOCATION;
-            }
+        int op = resolutionLevelToOp(allowedResolutionLevel);
+        if (op >= 0) {
             if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
@@ -1019,11 +1017,14 @@
         if (records != null) {
             for (UpdateRecord record : records) {
                 if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
-                    LocationRequest locationRequest = record.mRequest;
-                    providerRequest.locationRequests.add(locationRequest);
-                    if (locationRequest.getInterval() < providerRequest.interval) {
-                        providerRequest.reportLocation = true;
-                        providerRequest.interval = locationRequest.getInterval();
+                    if (checkLocationAccess(record.mReceiver.mUid, record.mReceiver.mPackageName,
+                            record.mReceiver.mAllowedResolutionLevel)) {
+                        LocationRequest locationRequest = record.mRequest;
+                        providerRequest.locationRequests.add(locationRequest);
+                        if (locationRequest.getInterval() < providerRequest.interval) {
+                            providerRequest.reportLocation = true;
+                            providerRequest.interval = locationRequest.getInterval();
+                        }
                     }
                 }
             }
@@ -1144,9 +1145,6 @@
      * and consistency requirements.
      *
      * @param request the LocationRequest from which to create a sanitized version
-     * @param shouldBeCoarse whether the sanitized version should be held to coarse resolution
-     * constraints
-     * @param fastestCoarseIntervalMS minimum interval allowed for coarse resolution
      * @return a version of request that meets the given resolution and consistency requirements
      * @hide
      */
@@ -1340,16 +1338,18 @@
         final int uid = Binder.getCallingUid();
         final long identity = Binder.clearCallingIdentity();
         try {
-            if (!reportLocationAccessNoThrow(uid, packageName, allowedResolutionLevel)) {
-                return null;
-            }
-            
             if (mBlacklist.isBlacklisted(packageName)) {
                 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
                         packageName);
                 return null;
             }
 
+            if (!reportLocationAccessNoThrow(uid, packageName, allowedResolutionLevel)) {
+                if (D) Log.d(TAG, "not returning last loc for no op app: " +
+                        packageName);
+                return null;
+            }
+
             synchronized (mLock) {
                 // Figure out the provider. Either its explicitly request (deprecated API's),
                 // or use the fused provider
@@ -1402,7 +1402,8 @@
         }
         long identity = Binder.clearCallingIdentity();
         try {
-            mGeofenceManager.addFence(sanitizedRequest, geofence, intent, uid, packageName);
+            mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
+                    uid, packageName);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -1703,6 +1704,13 @@
                 continue;
             }
 
+            if (!reportLocationAccessNoThrow(receiver.mUid, receiver.mPackageName,
+                    receiver.mAllowedResolutionLevel)) {
+                if (D) Log.d(TAG, "skipping loc update for no op app: " +
+                        receiver.mPackageName);
+                continue;
+            }
+
             Location notifyLocation = null;
             if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
                 notifyLocation = coarseLocation;  // use coarse location
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index de8a44b..0a54593 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -1468,32 +1468,6 @@
     }
 
     @Override
-    public void setDnsIfaceForPid(String iface, int pid) throws IllegalStateException {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        try {
-            String cmd = "resolver setifaceforpid " + iface + " " + pid;
-
-            mConnector.execute(cmd);
-        } catch (NativeDaemonConnectorException e) {
-            throw new IllegalStateException(
-                    "Error communicating with native deamon to set interface for pid" + iface, e);
-        }
-    }
-
-    @Override
-    public void clearDnsIfaceForPid(int pid) throws IllegalStateException {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        try {
-            String cmd = "resolver clearifaceforpid " + pid;
-
-            mConnector.execute(cmd);
-        } catch (NativeDaemonConnectorException e) {
-            throw new IllegalStateException(
-                    "Error communicating with native deamon to clear interface for pid " + pid, e);
-        }
-    }
-
-    /** {@inheritDoc} */
     public void monitor() {
         if (mConnector != null) {
             mConnector.monitor();
diff --git a/services/java/com/android/server/RecognitionManagerService.java b/services/java/com/android/server/RecognitionManagerService.java
index 1e0755d..c2e749d 100644
--- a/services/java/com/android/server/RecognitionManagerService.java
+++ b/services/java/com/android/server/RecognitionManagerService.java
@@ -89,17 +89,15 @@
     private void initForUser(int userHandle) {
         if (DEBUG) Slog.i(TAG, "initForUser user=" + userHandle);
         ComponentName comp = getCurRecognizer(userHandle);
+        ServiceInfo info = null;
         if (comp != null) {
-            // See if the current recognizer is no longer available.
+            // See if the current recognizer is still available.
             try {
-                mIPm.getServiceInfo(comp, 0, userHandle);
+                info = mIPm.getServiceInfo(comp, 0, userHandle);
             } catch (RemoteException e) {
-                comp = findAvailRecognizer(null, userHandle);
-                if (comp != null) {
-                    setCurRecognizer(comp, userHandle);
-                }
             }
-        } else {
+        }
+        if (info == null) {
             comp = findAvailRecognizer(null, userHandle);
             if (comp != null) {
                 setCurRecognizer(comp, userHandle);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 5789a53..ad6eb4d 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManager;
 import android.app.AlarmManager;
+import android.app.AppOpsManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -127,6 +128,7 @@
     private int mMulticastDisabled;
 
     private final IBatteryStats mBatteryStats;
+    private final AppOpsManager mAppOps;
 
     private boolean mEnableTrafficStatsPoll = false;
     private int mTrafficStatsPollToken = 0;
@@ -381,6 +383,7 @@
         mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);
         mWifiStateMachine.enableRssiPolling(true);
         mBatteryStats = BatteryStatsService.getService();
+        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
 
         mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
         Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
@@ -845,10 +848,15 @@
      * a list of {@link ScanResult} objects.
      * @return the list of results
      */
-    public List<ScanResult> getScanResults() {
+    public List<ScanResult> getScanResults(String callingPackage) {
         enforceAccessPermission();
         int userId = UserHandle.getCallingUserId();
+        int uid = Binder.getCallingUid();
         long ident = Binder.clearCallingIdentity();
+        if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage)
+                != AppOpsManager.MODE_ALLOWED) {
+            return new ArrayList<ScanResult>();
+        }
         try {
             int currentUser = ActivityManager.getCurrentUser();
             if (userId != currentUser) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d8e199b..e0046ad 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -262,6 +262,9 @@
     // Maximum number of users we allow to be running at a time.
     static final int MAX_RUNNING_USERS = 3;
 
+    // How long to wait in getTopActivityExtras for the activity to respond with the result.
+    static final int PENDING_ACTIVITY_RESULT_TIMEOUT = 2*2000;
+
     static final int MY_PID = Process.myPid();
     
     static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -319,11 +322,32 @@
      * Activity we have told the window manager to have key focus.
      */
     ActivityRecord mFocusedActivity = null;
+
     /**
      * List of intents that were used to start the most recent tasks.
      */
     final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
 
+    public class PendingActivityExtras extends Binder implements Runnable {
+        public final ActivityRecord activity;
+        public boolean haveResult = false;
+        public Bundle result = null;
+        public PendingActivityExtras(ActivityRecord _activity) {
+            activity = _activity;
+        }
+        @Override
+        public void run() {
+            Slog.w(TAG, "getTopActivityExtras failed: timeout retrieving from " + activity);
+            synchronized (this) {
+                haveResult = true;
+                notifyAll();
+            }
+        }
+    }
+
+    final ArrayList<PendingActivityExtras> mPendingActivityExtras
+            = new ArrayList<PendingActivityExtras>();
+
     /**
      * Process management.
      */
@@ -7451,6 +7475,63 @@
         return KEY_DISPATCHING_TIMEOUT;
     }
 
+    public Bundle getTopActivityExtras(int requestType) {
+        enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
+                "getTopActivityExtras()");
+        PendingActivityExtras pae;
+        Bundle extras = new Bundle();
+        synchronized (this) {
+            ActivityRecord activity = mMainStack.mResumedActivity;
+            if (activity == null) {
+                Slog.w(TAG, "getTopActivityExtras failed: no resumed activity");
+                return null;
+            }
+            extras.putString(Intent.EXTRA_ASSIST_PACKAGE, activity.packageName);
+            if (activity.app == null || activity.app.thread == null) {
+                Slog.w(TAG, "getTopActivityExtras failed: no process for " + activity);
+                return extras;
+            }
+            if (activity.app.pid == Binder.getCallingPid()) {
+                Slog.w(TAG, "getTopActivityExtras failed: request process same as " + activity);
+                return extras;
+            }
+            pae = new PendingActivityExtras(activity);
+            try {
+                activity.app.thread.requestActivityExtras(activity.appToken, pae, requestType);
+                mPendingActivityExtras.add(pae);
+                mHandler.postDelayed(pae, PENDING_ACTIVITY_RESULT_TIMEOUT);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "getTopActivityExtras failed: crash calling " + activity);
+                return extras;
+            }
+        }
+        synchronized (pae) {
+            while (!pae.haveResult) {
+                try {
+                    pae.wait();
+                } catch (InterruptedException e) {
+                }
+            }
+            if (pae.result != null) {
+                extras.putBundle(Intent.EXTRA_ASSIST_CONTEXT, pae.result);
+            }
+        }
+        synchronized (this) {
+            mPendingActivityExtras.remove(pae);
+            mHandler.removeCallbacks(pae);
+        }
+        return extras;
+    }
+
+    public void reportTopActivityExtras(IBinder token, Bundle extras) {
+        PendingActivityExtras pae = (PendingActivityExtras)token;
+        synchronized (pae) {
+            pae.result = extras;
+            pae.haveResult = true;
+            pae.notifyAll();
+        }
+    }
+
     public void registerProcessObserver(IProcessObserver observer) {
         enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
                 "registerProcessObserver()");
diff --git a/services/java/com/android/server/location/GeofenceManager.java b/services/java/com/android/server/location/GeofenceManager.java
index f9be719..e24bf76 100644
--- a/services/java/com/android/server/location/GeofenceManager.java
+++ b/services/java/com/android/server/location/GeofenceManager.java
@@ -21,6 +21,7 @@
 import java.util.LinkedList;
 import java.util.List;
 
+import android.app.AppOpsManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -68,6 +69,7 @@
 
     private final Context mContext;
     private final LocationManager mLocationManager;
+    private final AppOpsManager mAppOps;
     private final PowerManager.WakeLock mWakeLock;
     private final GeofenceHandler mHandler;
     private final LocationBlacklist mBlacklist;
@@ -107,6 +109,7 @@
     public GeofenceManager(Context context, LocationBlacklist blacklist) {
         mContext = context;
         mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+        mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
         PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         mHandler = new GeofenceHandler();
@@ -114,14 +117,14 @@
     }
 
     public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent,
-            int uid, String packageName) {
+            int allowedResolutionLevel, int uid, String packageName) {
         if (D) {
             Slog.d(TAG, "addFence: request=" + request + ", geofence=" + geofence
                     + ", intent=" + intent + ", uid=" + uid + ", packageName=" + packageName);
         }
 
         GeofenceState state = new GeofenceState(geofence,
-                request.getExpireAt(), packageName, intent);
+                request.getExpireAt(), allowedResolutionLevel, uid, packageName, intent);
         synchronized (mLock) {
             // first make sure it doesn't already exist
             for (int i = mFences.size() - 1; i >= 0; i--) {
@@ -261,6 +264,18 @@
                     continue;
                 }
 
+                int op = LocationManagerService.resolutionLevelToOp(state.mAllowedResolutionLevel);
+                if (op >= 0) {
+                    if (mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, state.mUid,
+                            state.mPackageName) != AppOpsManager.MODE_ALLOWED) {
+                        if (D) {
+                            Slog.d(TAG, "skipping geofence processing for no op app: "
+                                    + state.mPackageName);
+                        }
+                        continue;
+                    }
+                }
+
                 needUpdates = true;
                 if (location != null) {
                     int event = state.processLocation(location);
diff --git a/services/java/com/android/server/location/GeofenceState.java b/services/java/com/android/server/location/GeofenceState.java
index 11705ff..3ebe20a 100644
--- a/services/java/com/android/server/location/GeofenceState.java
+++ b/services/java/com/android/server/location/GeofenceState.java
@@ -35,6 +35,8 @@
     public final Geofence mFence;
     private final Location mLocation;
     public final long mExpireAt;
+    public final int mAllowedResolutionLevel;
+    public final int mUid;
     public final String mPackageName;
     public final PendingIntent mIntent;
 
@@ -42,12 +44,14 @@
     double mDistanceToCenter;  // current distance to center of fence
 
     public GeofenceState(Geofence fence, long expireAt,
-            String packageName, PendingIntent intent) {
+            int allowedResolutionLevel, int uid, String packageName, PendingIntent intent) {
         mState = STATE_UNKNOWN;
         mDistanceToCenter = Double.MAX_VALUE;
 
         mFence = fence;
         mExpireAt = expireAt;
+        mAllowedResolutionLevel = allowedResolutionLevel;
+        mUid = uid;
         mPackageName = packageName;
         mIntent = intent;
 
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 12c14bf..da150d9 100644
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -704,17 +704,17 @@
      */
     @Override
     public void enable() {
+        synchronized (mLock) {
+            if (mEnabled) return;
+            mEnabled = true;
+        }
+
         sendMessage(ENABLE, 1, null);
     }
 
     private void handleEnable() {
         if (DEBUG) Log.d(TAG, "handleEnable");
 
-        synchronized (mLock) {
-            if (mEnabled) return;
-            mEnabled = true;
-        }
-
         boolean enabled = native_init();
 
         if (enabled) {
@@ -740,17 +740,17 @@
      */
     @Override
     public void disable() {
+        synchronized (mLock) {
+            if (!mEnabled) return;
+            mEnabled = false;
+        }
+
         sendMessage(ENABLE, 0, null);
     }
 
     private void handleDisable() {
         if (DEBUG) Log.d(TAG, "handleDisable");
 
-        synchronized (mLock) {
-            if (!mEnabled) return;
-            mEnabled = false;
-        }
-
         stopNavigating();
         mAlarmManager.cancel(mWakeupIntent);
         mAlarmManager.cancel(mTimeoutIntent);
diff --git a/services/java/com/android/server/location/LocationBlacklist.java b/services/java/com/android/server/location/LocationBlacklist.java
index 2437a37..6f22689 100644
--- a/services/java/com/android/server/location/LocationBlacklist.java
+++ b/services/java/com/android/server/location/LocationBlacklist.java
@@ -67,9 +67,9 @@
 
     private void reloadBlacklistLocked() {
         mWhitelist = getStringArrayLocked(WHITELIST_CONFIG_NAME);
-        Slog.i(TAG, "whitelist: " + Arrays.toString(mWhitelist));
+        if (D) Slog.d(TAG, "whitelist: " + Arrays.toString(mWhitelist));
         mBlacklist = getStringArrayLocked(BLACKLIST_CONFIG_NAME);
-        Slog.i(TAG, "blacklist: " + Arrays.toString(mBlacklist));
+        if (D) Slog.d(TAG, "blacklist: " + Arrays.toString(mBlacklist));
     }
 
     private void reloadBlacklist() {
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 9b3795a..626002d 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -20,6 +20,7 @@
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 import static com.android.internal.util.ArrayUtils.appendInt;
@@ -1347,7 +1348,8 @@
                 continue;
             }
 
-            if (!ps.grantedPermissions
+            final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
+            if (!gp.grantedPermissions
                     .contains(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)) {
                 continue;
             }
@@ -2878,187 +2880,145 @@
         }
     }
 
-    private static final int getContinuationPoint(final String[] keys, final String key) {
-        final int index;
-        if (key == null) {
-            index = 0;
-        } else {
-            final int insertPoint = Arrays.binarySearch(keys, key);
-            if (insertPoint < 0) {
-                index = -insertPoint;
-            } else {
-                index = insertPoint + 1;
-            }
-        }
-        return index;
-    }
-
     @Override
-    public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, String lastRead,
-            int userId) {
-        final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
+    public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
         final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
-        final String[] keys;
 
         enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "get installed packages");
 
         // writer
         synchronized (mPackages) {
+            ArrayList<PackageInfo> list;
             if (listUninstalled) {
-                keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
-            } else {
-                keys = mPackages.keySet().toArray(new String[mPackages.size()]);
-            }
-
-            Arrays.sort(keys);
-            int i = getContinuationPoint(keys, lastRead);
-            final int N = keys.length;
-
-            while (i < N) {
-                final String packageName = keys[i++];
-
-                PackageInfo pi = null;
-                if (listUninstalled) {
-                    final PackageSetting ps = mSettings.mPackages.get(packageName);
-                    if (ps != null) {
+                list = new ArrayList<PackageInfo>(mSettings.mPackages.size());
+                for (PackageSetting ps : mSettings.mPackages.values()) {
+                    PackageInfo pi;
+                    if (ps.pkg != null) {
+                        pi = generatePackageInfo(ps.pkg, flags, userId);
+                    } else {
                         pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
                     }
-                } else {
-                    final PackageParser.Package p = mPackages.get(packageName);
-                    if (p != null) {
-                        pi = generatePackageInfo(p, flags, userId);
+                    if (pi != null) {
+                        list.add(pi);
                     }
                 }
-
-                if (pi != null && list.append(pi)) {
-                    break;
+            } else {
+                list = new ArrayList<PackageInfo>(mPackages.size());
+                for (PackageParser.Package p : mPackages.values()) {
+                    PackageInfo pi = generatePackageInfo(p, flags, userId);
+                    if (pi != null) {
+                        list.add(pi);
+                    }
                 }
             }
 
-            if (i == N) {
-                list.setLastSlice(true);
+            return new ParceledListSlice<PackageInfo>(list);
+        }
+    }
+
+    private void addPackageHoldingPermissions(ArrayList<PackageInfo> list, PackageSetting ps,
+            String[] permissions, boolean[] tmp, int flags, int userId) {
+        int numMatch = 0;
+        final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
+        for (int i=0; i<permissions.length; i++) {
+            if (gp.grantedPermissions.contains(permissions[i])) {
+                tmp[i] = true;
+                numMatch++;
+            } else {
+                tmp[i] = false;
             }
         }
-
-        return list;
+        if (numMatch == 0) {
+            return;
+        }
+        PackageInfo pi;
+        if (ps.pkg != null) {
+            pi = generatePackageInfo(ps.pkg, flags, userId);
+        } else {
+            pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
+        }
+        if ((flags&PackageManager.GET_PERMISSIONS) == 0) {
+            if (numMatch == permissions.length) {
+                pi.requestedPermissions = permissions;
+            } else {
+                pi.requestedPermissions = new String[numMatch];
+                numMatch = 0;
+                for (int i=0; i<permissions.length; i++) {
+                    if (tmp[i]) {
+                        pi.requestedPermissions[numMatch] = permissions[i];
+                        numMatch++;
+                    }
+                }
+            }
+        }
+        list.add(pi);
     }
 
     @Override
     public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
-            String[] permissions, int flags, String lastRead, int userId) {
+            String[] permissions, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
-        final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
         final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
 
         // writer
         synchronized (mPackages) {
-            ArrayList<String> keysList = new ArrayList<String>();
+            ArrayList<PackageInfo> list = new ArrayList<PackageInfo>();
+            boolean[] tmpBools = new boolean[permissions.length];
             if (listUninstalled) {
                 for (PackageSetting ps : mSettings.mPackages.values()) {
-                    for (String perm : permissions) {
-                        if (ps.grantedPermissions.contains(perm)) {
-                            keysList.add(ps.name);
-                            break;
-                        }
-                    }
+                    addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags, userId);
                 }
             } else {
                 for (PackageParser.Package pkg : mPackages.values()) {
                     PackageSetting ps = (PackageSetting)pkg.mExtras;
                     if (ps != null) {
-                        for (String perm : permissions) {
-                            if (ps.grantedPermissions.contains(perm)) {
-                                keysList.add(ps.name);
-                                break;
-                            }
+                        addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags,
+                                userId);
+                    }
+                }
+            }
+
+            return new ParceledListSlice<PackageInfo>(list);
+        }
+    }
+
+    @Override
+    public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
+        if (!sUserManager.exists(userId)) return null;
+        final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
+
+        // writer
+        synchronized (mPackages) {
+            ArrayList<ApplicationInfo> list;
+            if (listUninstalled) {
+                list = new ArrayList<ApplicationInfo>(mSettings.mPackages.size());
+                for (PackageSetting ps : mSettings.mPackages.values()) {
+                    ApplicationInfo ai;
+                    if (ps.pkg != null) {
+                        ai = PackageParser.generateApplicationInfo(ps.pkg, flags,
+                                ps.readUserState(userId), userId);
+                    } else {
+                        ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
+                    }
+                    if (ai != null) {
+                        list.add(ai);
+                    }
+                }
+            } else {
+                list = new ArrayList<ApplicationInfo>(mPackages.size());
+                for (PackageParser.Package p : mPackages.values()) {
+                    if (p.mExtras != null) {
+                        ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
+                                ((PackageSetting)p.mExtras).readUserState(userId), userId);
+                        if (ai != null) {
+                            list.add(ai);
                         }
                     }
                 }
             }
 
-            String[] keys = new String[keysList.size()];
-            keysList.toArray(keys);
-            Arrays.sort(keys);
-            int i = getContinuationPoint(keys, lastRead);
-            final int N = keys.length;
-
-            while (i < N) {
-                final String packageName = keys[i++];
-
-                PackageInfo pi = null;
-                if (listUninstalled) {
-                    final PackageSetting ps = mSettings.mPackages.get(packageName);
-                    if (ps != null) {
-                        pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
-                    }
-                } else {
-                    final PackageParser.Package p = mPackages.get(packageName);
-                    if (p != null) {
-                        pi = generatePackageInfo(p, flags, userId);
-                    }
-                }
-
-                if (pi != null && list.append(pi)) {
-                    break;
-                }
-            }
-
-            if (i == N) {
-                list.setLastSlice(true);
-            }
+            return new ParceledListSlice<ApplicationInfo>(list);
         }
-
-        return list;
-    }
-
-    @Override
-    public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags,
-            String lastRead, int userId) {
-        if (!sUserManager.exists(userId)) return null;
-        final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>();
-        final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
-        final String[] keys;
-
-        // writer
-        synchronized (mPackages) {
-            if (listUninstalled) {
-                keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
-            } else {
-                keys = mPackages.keySet().toArray(new String[mPackages.size()]);
-            }
-
-            Arrays.sort(keys);
-            int i = getContinuationPoint(keys, lastRead);
-            final int N = keys.length;
-
-            while (i < N) {
-                final String packageName = keys[i++];
-
-                ApplicationInfo ai = null;
-                final PackageSetting ps = mSettings.mPackages.get(packageName);
-                if (listUninstalled) {
-                    if (ps != null) {
-                        ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
-                    }
-                } else {
-                    final PackageParser.Package p = mPackages.get(packageName);
-                    if (p != null && ps != null) {
-                        ai = PackageParser.generateApplicationInfo(p, flags,
-                                ps.readUserState(userId), userId);
-                    }
-                }
-
-                if (ai != null && list.append(ai)) {
-                    break;
-                }
-            }
-
-            if (i == N) {
-                list.setLastSlice(true);
-            }
-        }
-
-        return list;
     }
 
     public List<ApplicationInfo> getPersistentApplications(int flags) {
@@ -3339,6 +3299,13 @@
                     Log.i(TAG, "Package " + ps.name + " at " + scanFile
                             + " ignored: updated version " + ps.versionCode
                             + " better than this " + pkg.mVersionCode);
+                    if (!updatedPkg.codePath.equals(scanFile)) {
+                        Slog.w(PackageManagerService.TAG, "Code path for hidden system pkg : "
+                                + ps.name + " changing from " + updatedPkg.codePathString
+                                + " to " + scanFile);
+                        updatedPkg.codePath = scanFile;
+                        updatedPkg.codePathString = scanFile.toString();                        
+                    }
                     mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
                     return null;
                 } else {
@@ -8949,13 +8916,14 @@
         if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
               || newState == COMPONENT_ENABLED_STATE_ENABLED
               || newState == COMPONENT_ENABLED_STATE_DISABLED
-              || newState == COMPONENT_ENABLED_STATE_DISABLED_USER)) {
+              || newState == COMPONENT_ENABLED_STATE_DISABLED_USER
+              || newState == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
             throw new IllegalArgumentException("Invalid new component state: "
                     + newState);
         }
         PackageSetting pkgSetting;
         final int uid = Binder.getCallingUid();
-        final int permission = mContext.checkCallingPermission(
+        final int permission = mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
         enforceCrossUserPermission(uid, userId, false, "set enabled");
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 06f11bc..e336524 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
@@ -2412,8 +2413,14 @@
             return false;
         }
         PackageUserState ustate = packageSettings.readUserState(userId);
+        if ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0) {
+            if (ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+                return true;
+            }
+        }
         if (ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED
                 || ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
+                || ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
                 || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
                     && ustate.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
             return false;
diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/java/com/android/server/usb/UsbSettingsManager.java
index 4b2bbfe..f9aaa17 100644
--- a/services/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/java/com/android/server/usb/UsbSettingsManager.java
@@ -364,8 +364,9 @@
         }
 
         @Override
-        public void onPackageChanged(String packageName, int uid, String[] components) {
+        public boolean onPackageChanged(String packageName, int uid, String[] components) {
             handlePackageUpdate(packageName);
+            return false;
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 167b6c2..47ce130 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -557,6 +557,25 @@
         }
     }
 
+    public void testCycleTodayJanuary() throws Exception {
+        final NetworkPolicy policy = new NetworkPolicy(
+                sTemplateWifi, 14, "US/Pacific", 1024L, 1024L, false);
+
+        assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"),
+                computeNextCycleBoundary(parseTime("2013-01-13T23:59:59.000-08:00"), policy));
+        assertTimeEquals(parseTime("2013-02-14T00:00:00.000-08:00"),
+                computeNextCycleBoundary(parseTime("2013-01-14T00:00:01.000-08:00"), policy));
+        assertTimeEquals(parseTime("2013-02-14T00:00:00.000-08:00"),
+                computeNextCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
+
+        assertTimeEquals(parseTime("2012-12-14T00:00:00.000-08:00"),
+                computeLastCycleBoundary(parseTime("2013-01-13T23:59:59.000-08:00"), policy));
+        assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"),
+                computeLastCycleBoundary(parseTime("2013-01-14T00:00:01.000-08:00"), policy));
+        assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"),
+                computeLastCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
+    }
+
     public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
         NetworkState[] state = null;
         NetworkStats stats = null;
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index e2da53e..3ed9cef 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -335,7 +335,7 @@
         mCdmaEcio = (mCdmaEcio > 0) ? -mCdmaEcio : -160;
 
         mEvdoDbm = (mEvdoDbm > 0) ? -mEvdoDbm : -120;
-        mEvdoEcio = (mEvdoEcio > 0) ? -mEvdoEcio : -1;
+        mEvdoEcio = (mEvdoEcio >= 0) ? -mEvdoEcio : -1;
         mEvdoSnr = ((mEvdoSnr > 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
 
         // TS 36.214 Physical Layer Section 5.1.3, TS 36.331 RRC
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 3097811..248fbf1 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -106,6 +106,12 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public String getBasePackageName() {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public ApplicationInfo getApplicationInfo() {
         throw new UnsupportedOperationException();
diff --git a/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestActivity.java b/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestActivity.java
index 1b72486..ab60f21 100644
--- a/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestActivity.java
+++ b/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestActivity.java
@@ -21,6 +21,7 @@
 import android.graphics.Bitmap;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.util.Log;
 import android.view.ViewGroup;
@@ -180,7 +181,7 @@
     }
 
     private final void validateNotAppThread() {
-        if (ActivityThread.currentActivityThread() != null) {
+        if (Looper.myLooper() == Looper.getMainLooper()) {
             throw new RuntimeException(
                 "This method can not be called from the main application thread");
         }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
index 9a4e99e..22b587f 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
@@ -22,6 +22,7 @@
 import android.net.http.SslError;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.util.Log;
 import android.view.ViewGroup;
@@ -184,7 +185,7 @@
     }
 
     private final void validateNotAppThread() {
-        if (ActivityThread.currentActivityThread() != null) {
+        if (Looper.myLooper() == Looper.getMainLooper()) {
             throw new RuntimeException(
                 "This method can not be called from the main application thread");
         }
diff --git a/tests/HwAccelerationTest/res/layout/view_layers_5.xml b/tests/HwAccelerationTest/res/layout/view_layers_5.xml
index 36cf8c9..5baf583 100644
--- a/tests/HwAccelerationTest/res/layout/view_layers_5.xml
+++ b/tests/HwAccelerationTest/res/layout/view_layers_5.xml
@@ -48,13 +48,32 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="Grow layer" />
+
+        <Button
+            android:onClick="enableClip"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Circle clip" />
+
+        <Button
+            android:onClick="disableClip"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="No clip" />
         
     </LinearLayout>
 
-    <ListView
-        android:id="@+id/list1"
+    <view class="com.android.test.hwui.ViewLayersActivity5$ClipFrameLayout"
+        android:id="@+id/container"
         android:layout_width="0dip"
         android:layout_height="match_parent"
-        android:layout_weight="1" />
+        android:layout_weight="1">
+
+        <ListView
+            android:id="@+id/list1"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+    </view>
 
 </LinearLayout>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
index 2664977..cbbb7ef 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
@@ -19,14 +19,18 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Canvas;
 import android.graphics.Paint;
+import android.graphics.Path;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.os.Bundle;
+import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
+import android.widget.FrameLayout;
 import android.widget.ListView;
 import android.widget.TextView;
 
@@ -37,30 +41,75 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        
+
+        init();
+
         setContentView(R.layout.view_layers_5);
-
-        mPaint.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
-
         setupList(R.id.list1);
     }
 
+    public static class ClipFrameLayout extends FrameLayout {
+        private final Path mClipPath = new Path();
+        private boolean mClipEnabled;
+
+        public ClipFrameLayout(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        public ClipFrameLayout(Context context, AttributeSet attrs, int defStyle) {
+            super(context, attrs, defStyle);
+        }
+
+        public boolean isClipEnabled() {
+            return mClipEnabled;
+        }
+
+        public void setClipEnabled(boolean clipEnabled) {
+            mClipEnabled = clipEnabled;
+            invalidate();
+        }
+
+        @Override
+        protected void dispatchDraw(Canvas canvas) {
+            if (mClipEnabled) {
+                mClipPath.reset();
+                mClipPath.addCircle(getWidth() / 2.0f, getHeight() / 2.0f,
+                        Math.min(getWidth(), getHeight()) / 3.0f, Path.Direction.CW);
+
+                canvas.clipPath(mClipPath);
+            }
+            super.dispatchDraw(canvas);
+        }
+    }
+
+    private void init() {
+        mPaint.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
+    }
+
+    public void enableClip(View v) {
+        ((ClipFrameLayout) findViewById(R.id.container)).setClipEnabled(true);
+    }
+
+    public void disableClip(View v) {
+        ((ClipFrameLayout) findViewById(R.id.container)).setClipEnabled(false);
+    }
+
     public void enableLayer(View v) {
-        findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
+        findViewById(R.id.container).setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
     }
 
     public void disableLayer(View v) {
-        findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_NONE, null);
+        findViewById(R.id.container).setLayerType(View.LAYER_TYPE_NONE, null);
     }
     
     public void growLayer(View v) {
-        findViewById(R.id.list1).getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
-        findViewById(R.id.list1).requestLayout();
+        findViewById(R.id.container).getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
+        findViewById(R.id.container).requestLayout();
     }
 
     public void shrinkLayer(View v) {
-        findViewById(R.id.list1).getLayoutParams().height = 300;
-        findViewById(R.id.list1).requestLayout();
+        findViewById(R.id.container).getLayoutParams().height = 300;
+        findViewById(R.id.container).requestLayout();
     }
     
     private void setupList(int listId) {
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/bwfilter.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/bwfilter.rs
index 2818bf5..03e5a79 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/bwfilter.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/bwfilter.rs
@@ -16,7 +16,7 @@
 
 #pragma version(1)
 #pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+//#pragma rs_fp_relaxed
 
 static float sr = 0.f;
 static float sg = 0.f;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/shadows.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/shadows.rs
index 81cb9d0..7ee3405 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/shadows.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/shadows.rs
@@ -16,7 +16,7 @@
 
 #pragma version(1)
 #pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+//#pragma rs_fp_relaxed
 
 static double shadowFilterMap[] = {
     -0.00591,  0.0001,
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vibrance.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vibrance.rs
index 677e857..fae94a1 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vibrance.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vibrance.rs
@@ -16,7 +16,6 @@
 
 #pragma version(1)
 #pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
 
 float vibrance = 0.f;
 
@@ -39,7 +38,7 @@
     int g = in->g;
     int b = in->b;
     float red = (r-max(g, b))/256.f;
-    float sx = (float)(Vib/(1+exp(-red*3)));
+    float sx = (float)(Vib/(1+native_exp(-red*3)));
     S = sx+1;
     MS = 1.0f - S;
     Rt = Rf * MS;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh
index 05a5929..5668621 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh
@@ -50,8 +50,7 @@
     const float2 inCoord = {(float)x, (float)y};
     const float2 coord = mad(inCoord, inv_dimensions, neg_center);
     const float sloped_dist_ratio = fast_length(axis_scale * coord)  * sloped_inv_max_dist;
-    // TODO:  add half_exp once implemented
-    const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * exp(sloped_dist_ratio));
+    const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * native_exp(sloped_dist_ratio));
     float4 fout;
     fout.rgb = fin.rgb * lumen;
     fout.w = fin.w;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/wbalance.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/wbalance.rs
index b9c28fc..8c825f2 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/wbalance.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/wbalance.rs
@@ -16,7 +16,7 @@
 
 #pragma version(1)
 #pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+//#pragma rs_fp_relaxed
 
 static int histR[256] = {0}, histG[256] = {0}, histB[256] = {0};
 
diff --git a/tests/RenderScriptTests/MathErr/Android.mk b/tests/RenderScriptTests/MathErr/Android.mk
new file mode 100644
index 0000000..b3edd02
--- /dev/null
+++ b/tests/RenderScriptTests/MathErr/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RsMathErr
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/MathErr/AndroidManifest.xml b/tests/RenderScriptTests/MathErr/AndroidManifest.xml
new file mode 100644
index 0000000..6a3db2c
--- /dev/null
+++ b/tests/RenderScriptTests/MathErr/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.rs.matherr">
+
+    <uses-sdk android:minSdkVersion="17" />
+    <application android:label="RS Math Err">
+        <activity android:name="MathErrActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/RenderScriptTests/MathErr/res/layout/main.xml b/tests/RenderScriptTests/MathErr/res/layout/main.xml
new file mode 100644
index 0000000..7b2c76a
--- /dev/null
+++ b/tests/RenderScriptTests/MathErr/res/layout/main.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/displayin"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+    <ImageView
+        android:id="@+id/displayout"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+</LinearLayout>
diff --git a/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/MathErr.java b/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/MathErr.java
new file mode 100644
index 0000000..4561267
--- /dev/null
+++ b/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/MathErr.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.rs.matherr;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import java.lang.Float;
+import java.lang.Math;
+
+public class MathErr {
+    private RenderScript mRS;
+    private Allocation mAllocationSrc;
+    private Allocation mAllocationRes;
+    private ScriptC_math_err mScript;
+    private java.util.Random mRand = new java.util.Random();
+
+    private final int BUF_SIZE = 4096;
+    float mSrc[] = new float[BUF_SIZE];
+    float mRef[] = new float[BUF_SIZE];
+    float mRes[] = new float[BUF_SIZE];
+
+    MathErr(RenderScript rs) {
+        mRS = rs;
+        mScript = new ScriptC_math_err(mRS);
+
+        mAllocationSrc = Allocation.createSized(rs, Element.F32(rs), BUF_SIZE);
+        mAllocationRes = Allocation.createSized(rs, Element.F32(rs), BUF_SIZE);
+
+        testExp2();
+        testLog2();
+    }
+
+    void buildRand() {
+        for (int i=0; i < BUF_SIZE; i++) {
+            mSrc[i] = (((float)i) / 9) - 200;
+            //mSrc[i] = Float.intBitsToFloat(mRand.nextInt());
+        }
+        mAllocationSrc.copyFrom(mSrc);
+    }
+
+    void logErr() {
+        mAllocationRes.copyTo(mRes);
+        for (int i=0; i < BUF_SIZE; i++) {
+            int err = Float.floatToRawIntBits(mRef[i]) - Float.floatToRawIntBits(mRes[i]);
+            err = Math.abs(err);
+            if (err > 8096) {
+                android.util.Log.v("err", "error " + err + " src " + mSrc[i] + " ref " + mRef[i] + " res " + mRes[i]);
+            }
+        }
+    }
+
+    void testExp2() {
+        android.util.Log.v("err", "testing exp2");
+        buildRand();
+        mScript.forEach_testExp2(mAllocationSrc, mAllocationRes);
+        for (int i=0; i < BUF_SIZE; i++) {
+            mRef[i] = (float)Math.pow(2.f, mSrc[i]);
+        }
+        logErr();
+    }
+
+    void testLog2() {
+        android.util.Log.v("err", "testing log2");
+        buildRand();
+        mScript.forEach_testLog2(mAllocationSrc, mAllocationRes);
+        for (int i=0; i < BUF_SIZE; i++) {
+            mRef[i] = (float)Math.log(mSrc[i]) * 1.442695041f;
+        }
+        logErr();
+    }
+
+}
diff --git a/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/MathErrActivity.java b/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/MathErrActivity.java
new file mode 100644
index 0000000..74d7b71
--- /dev/null
+++ b/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/MathErrActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.rs.matherr;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.renderscript.RenderScript;
+import android.renderscript.Allocation;
+import android.util.Log;
+
+public class MathErrActivity extends Activity {
+    private MathErr mME;
+    private RenderScript mRS;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mRS = RenderScript.create(this);
+        mME = new MathErr(mRS);
+    }
+}
diff --git a/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/math_err.rs b/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/math_err.rs
new file mode 100644
index 0000000..a26770b
--- /dev/null
+++ b/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/math_err.rs
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.matherr)
+
+typedef union
+{
+  float fv;
+  int32_t iv;
+} ieee_float_shape_type;
+
+/* Get a 32 bit int from a float.  */
+
+#define GET_FLOAT_WORD(i,d)         \
+do {                                \
+  ieee_float_shape_type gf_u;       \
+  gf_u.fv = (d);                    \
+  (i) = gf_u.iv;                    \
+} while (0)
+
+/* Set a float from a 32 bit int.  */
+
+#define SET_FLOAT_WORD(d,i)         \
+do {                                \
+  ieee_float_shape_type sf_u;       \
+  sf_u.iv = (i);                    \
+  (d) = sf_u.fv;                    \
+} while (0)
+
+
+static float fast_log2(float v) {
+    int32_t ibits;
+    GET_FLOAT_WORD(ibits, v);
+
+    int32_t e = (ibits >> 23) & 0xff;
+
+    ibits &= 0x7fffff;
+    ibits |= 127 << 23;
+
+    float ir;
+    SET_FLOAT_WORD(ir, ibits);
+
+    ir -= 1.5f;
+    float ir2 = ir*ir;
+    float adj2 = 0.405465108f + // -0.00009f +
+                 (0.666666667f * ir) -
+                 (0.222222222f * ir2) +
+                 (0.098765432f * ir*ir2) -
+                 (0.049382716f * ir2*ir2) +
+                 (0.026337449f * ir*ir2*ir2) -
+                 (0.014631916f * ir2*ir2*ir2);
+    adj2 *= (1.f / 0.693147181f);
+
+    return (float)(e - 127) + adj2;
+}
+
+void testExp2(const float *in, float *out) {
+    float i = *in;
+    if (i > (-125.f) && i < 125.f) {
+        *out = native_exp2(i);
+    } else {
+        *out = exp2(i);
+    }
+    *out = native_exp2(i);
+}
+
+void testLog2(const float *in, float *out) {
+    *out = fast_log2(*in);
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/Android.mk b/tests/RenderScriptTests/RSTest_CompatLib/Android.mk
new file mode 100644
index 0000000..0fd0d96
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/Android.mk
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RSTest_Compat
+
+LOCAL_STATIC_JAVA_LIBRARIES := android.support.v8.renderscript
+
+LOCAL_SDK_VERSION := 8
+LOCAL_RENDERSCRIPT_TARGET_API := 18
+LOCAL_RENDERSCRIPT_COMPATIBILITY := 18
+
+LOCAL_RENDERSCRIPT_CC := $(LLVM_RS_CC)
+LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE := \
+    $(TOPDIR)external/clang/lib/Headers \
+    $(TOPDIR)frameworks/rs/scriptc
+
+LOCAL_RENDERSCRIPT_FLAGS := -rs-package-name=android.support.v8.renderscript
+LOCAL_REQUIRED_MODULES := librsjni
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/AndroidManifest.xml b/tests/RenderScriptTests/RSTest_CompatLib/AndroidManifest.xml
new file mode 100644
index 0000000..53219e7
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.test_compat">
+  <uses-sdk android:minSdkVersion="8" />
+  <uses-sdk android:targetSdkVersion="8" />
+    <application
+        android:label="_RS_Test_Compat"
+        android:icon="@drawable/test_pattern">
+        <activity android:name="RSTest"
+                  android:screenOrientation="portrait">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/res/drawable-nodpi/test_pattern.png b/tests/RenderScriptTests/RSTest_CompatLib/res/drawable-nodpi/test_pattern.png
new file mode 100644
index 0000000..e7d1455
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/res/drawable-nodpi/test_pattern.png
Binary files differ
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/RSTest.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/RSTest.java
new file mode 100644
index 0000000..b76f21e
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/RSTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.support.v8.renderscript.RenderScript;
+
+import android.app.ListActivity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+import android.widget.ArrayAdapter;
+
+import java.lang.Runtime;
+
+public class RSTest extends ListActivity {
+
+    private static final String LOG_TAG = "RSTest_Compat";
+    private static final boolean DEBUG  = false;
+    private static final boolean LOG_ENABLED = false;
+
+    private RenderScript mRS;
+    private RSTestCore RSTC;
+
+    String mTestNames[];
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        mRS = RenderScript.create(this);
+
+        RSTC = new RSTestCore(this);
+        RSTC.init(mRS, getResources());
+
+
+
+
+    }
+
+    static void log(String message) {
+        if (LOG_ENABLED) {
+            Log.v(LOG_TAG, message);
+        }
+    }
+
+
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/RSTestCore.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/RSTestCore.java
new file mode 100644
index 0000000..51f8a4d
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/RSTestCore.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2008-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import java.util.ArrayList;
+import java.util.ListIterator;
+import java.util.Timer;
+import java.util.TimerTask;
+import android.app.ListActivity;
+import android.widget.ArrayAdapter;
+
+public class RSTestCore {
+    ListActivity mCtx;
+
+    public RSTestCore(ListActivity ctx) {
+        mCtx = ctx;
+    }
+
+    private Resources mRes;
+    private RenderScript mRS;
+
+    private ArrayList<UnitTest> unitTests;
+    private ListIterator<UnitTest> test_iter;
+    private UnitTest activeTest;
+    private boolean stopTesting;
+
+    private ScriptField_ListAllocs_s mListAllocs;
+
+    private ArrayAdapter<UnitTest> testAdapter;
+
+    /* Periodic timer for ensuring future tests get scheduled */
+    private Timer mTimer;
+    public static final int RS_TIMER_PERIOD = 100;
+
+    public void init(RenderScript rs, Resources res) {
+        mRS = rs;
+        mRes = res;
+        stopTesting = false;
+
+        unitTests = new ArrayList<UnitTest>();
+
+        unitTests.add(new UT_primitives(this, mRes, mCtx));
+        unitTests.add(new UT_constant(this, mRes, mCtx));
+        unitTests.add(new UT_vector(this, mRes, mCtx));
+        unitTests.add(new UT_unsigned(this, mRes, mCtx));
+        unitTests.add(new UT_array_init(this, mRes, mCtx));
+        unitTests.add(new UT_array_alloc(this, mRes, mCtx));
+        unitTests.add(new UT_kernel(this, mRes, mCtx));
+        unitTests.add(new UT_kernel_struct(this, mRes, mCtx));
+        unitTests.add(new UT_bug_char(this, mRes, mCtx));
+        unitTests.add(new UT_clamp(this, mRes, mCtx));
+        unitTests.add(new UT_clamp_relaxed(this, mRes, mCtx));
+        unitTests.add(new UT_convert(this, mRes, mCtx));
+        unitTests.add(new UT_convert_relaxed(this, mRes, mCtx));
+        unitTests.add(new UT_copy_test(this, mRes, mCtx));
+        unitTests.add(new UT_rsdebug(this, mRes, mCtx));
+        unitTests.add(new UT_rstime(this, mRes, mCtx));
+        unitTests.add(new UT_rstypes(this, mRes, mCtx));
+        unitTests.add(new UT_alloc(this, mRes, mCtx));
+        unitTests.add(new UT_refcount(this, mRes, mCtx));
+        unitTests.add(new UT_foreach(this, mRes, mCtx));
+        unitTests.add(new UT_foreach_bounds(this, mRes, mCtx));
+        unitTests.add(new UT_noroot(this, mRes, mCtx));
+        unitTests.add(new UT_atomic(this, mRes, mCtx));
+        unitTests.add(new UT_struct(this, mRes, mCtx));
+        unitTests.add(new UT_math(this, mRes, mCtx));
+        unitTests.add(new UT_math_conformance(this, mRes, mCtx));
+        unitTests.add(new UT_math_agree(this, mRes, mCtx));
+        unitTests.add(new UT_min(this, mRes, mCtx));
+        unitTests.add(new UT_int4(this, mRes, mCtx));
+        unitTests.add(new UT_element(this, mRes, mCtx));
+        unitTests.add(new UT_sampler(this, mRes, mCtx));
+        unitTests.add(new UT_fp_mad(this, mRes, mCtx));
+
+        /*
+        unitTests.add(new UnitTest(null, "<Pass>", 1));
+        unitTests.add(new UnitTest());
+        unitTests.add(new UnitTest(null, "<Fail>", -1));
+
+        for (int i = 0; i < 20; i++) {
+            unitTests.add(new UnitTest(null, "<Pass>", 1));
+        }
+        */
+
+        UnitTest [] uta = new UnitTest[unitTests.size()];
+        uta = unitTests.toArray(uta);
+
+        mListAllocs = new ScriptField_ListAllocs_s(mRS, uta.length);
+        for (int i = 0; i < uta.length; i++) {
+
+            ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item();
+            listElem.text = Allocation.createFromString(mRS, uta[i].name, Allocation.USAGE_SCRIPT);
+            listElem.result = uta[i].getResult();
+            mListAllocs.set(listElem, i, false);
+            uta[i].setItem(listElem);
+        }
+
+        mListAllocs.copyAll();
+
+        testAdapter = new ArrayAdapter<UnitTest>(mCtx, android.R.layout.simple_list_item_1, unitTests);
+        mCtx.setListAdapter(testAdapter);
+
+        test_iter = unitTests.listIterator();
+        refreshTestResults(); /* Kick off the first test */
+
+        TimerTask pTask = new TimerTask() {
+            public void run() {
+                refreshTestResults();
+            }
+        };
+
+        mTimer = new Timer();
+        mTimer.schedule(pTask, RS_TIMER_PERIOD, RS_TIMER_PERIOD);
+    }
+
+    public void checkAndRunNextTest() {
+        mCtx.runOnUiThread(new Runnable() {
+                public void run() {
+                    if (testAdapter != null)
+                        testAdapter.notifyDataSetChanged();
+                }
+            });
+
+        if (activeTest != null) {
+            if (!activeTest.isAlive()) {
+                /* Properly clean up on our last test */
+                try {
+                    activeTest.join();
+                }
+                catch (InterruptedException e) {
+                }
+                activeTest = null;
+            }
+        }
+
+        if (!stopTesting && activeTest == null) {
+            if (test_iter.hasNext()) {
+                activeTest = test_iter.next();
+                activeTest.start();
+                /* This routine will only get called once when a new test
+                 * should start running. The message handler in UnitTest.java
+                 * ensures this. */
+            }
+            else {
+                if (mTimer != null) {
+                    mTimer.cancel();
+                    mTimer.purge();
+                    mTimer = null;
+                }
+            }
+        }
+    }
+
+    public void refreshTestResults() {
+        checkAndRunNextTest();
+    }
+
+    public void cleanup() {
+        stopTesting = true;
+        UnitTest t = activeTest;
+
+        /* Stop periodic refresh of testing */
+        if (mTimer != null) {
+            mTimer.cancel();
+            mTimer.purge();
+            mTimer = null;
+        }
+
+        /* Wait to exit until we finish the current test */
+        if (t != null) {
+            try {
+                t.join();
+            }
+            catch (InterruptedException e) {
+            }
+            t = null;
+        }
+
+    }
+
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java
new file mode 100644
index 0000000..ddc6a99
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_alloc extends UnitTest {
+    private Resources mRes;
+
+    protected UT_alloc(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Alloc", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_alloc s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        int Z = 0;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        s.set_dimZ(Z);
+        typeBuilder.setX(X).setY(Y);
+        Allocation A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_a(A);
+
+        typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        typeBuilder.setX(X).setY(Y).setFaces(true);
+        Allocation AFaces = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aFaces(AFaces);
+        typeBuilder.setFaces(false).setMipmaps(true);
+        Allocation ALOD = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aLOD(ALOD);
+        typeBuilder.setFaces(true).setMipmaps(true);
+        Allocation AFacesLOD = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aFacesLOD(AFacesLOD);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_alloc s = new ScriptC_alloc(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_alloc_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_array_alloc.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_array_alloc.java
new file mode 100644
index 0000000..751187b
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_array_alloc.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_array_alloc extends UnitTest {
+    private Resources mRes;
+
+    protected UT_array_alloc(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Array Allocation", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_array_alloc s = new ScriptC_array_alloc(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        int dimX = s.get_dimX();
+        Allocation[] Arr = new Allocation[dimX];
+        Type.Builder typeBuilder = new Type.Builder(pRS, Element.I32(pRS));
+        Type T = typeBuilder.setX(1).create();
+        for (int i = 0; i < dimX; i++) {
+            Allocation A = Allocation.createTyped(pRS, T);
+            Arr[i] = A;
+        }
+        s.set_a(Arr);
+
+        s.invoke_array_alloc_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+        passTest();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_array_init.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_array_init.java
new file mode 100644
index 0000000..f8b2fd3
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_array_init.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_array_init extends UnitTest {
+    private Resources mRes;
+
+    protected UT_array_init(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Array Init", ctx);
+        mRes = res;
+    }
+
+    private void checkInit(ScriptC_array_init s) {
+        float[] fa = s.get_fa();
+        _RS_ASSERT("fa[0] == 1.0", fa[0] == 1.0);
+        _RS_ASSERT("fa[1] == 9.9999f", fa[1] == 9.9999f);
+        _RS_ASSERT("fa[2] == 0", fa[2] == 0);
+        _RS_ASSERT("fa[3] == 0", fa[3] == 0);
+        _RS_ASSERT("fa.length == 4", fa.length == 4);
+
+        double[] da = s.get_da();
+        _RS_ASSERT("da[0] == 7.0", da[0] == 7.0);
+        _RS_ASSERT("da[1] == 8.88888", da[1] == 8.88888);
+        _RS_ASSERT("da.length == 2", da.length == 2);
+
+        byte[] ca = s.get_ca();
+        _RS_ASSERT("ca[0] == 'a'", ca[0] == 'a');
+        _RS_ASSERT("ca[1] == 7", ca[1] == 7);
+        _RS_ASSERT("ca[2] == 'b'", ca[2] == 'b');
+        _RS_ASSERT("ca[3] == 'c'", ca[3] == 'c');
+        _RS_ASSERT("ca.length == 4", ca.length == 4);
+
+        short[] sa = s.get_sa();
+        _RS_ASSERT("sa[0] == 1", sa[0] == 1);
+        _RS_ASSERT("sa[1] == 1", sa[1] == 1);
+        _RS_ASSERT("sa[2] == 2", sa[2] == 2);
+        _RS_ASSERT("sa[3] == 3", sa[3] == 3);
+        _RS_ASSERT("sa.length == 4", sa.length == 4);
+
+        int[] ia = s.get_ia();
+        _RS_ASSERT("ia[0] == 5", ia[0] == 5);
+        _RS_ASSERT("ia[1] == 8", ia[1] == 8);
+        _RS_ASSERT("ia[2] == 0", ia[2] == 0);
+        _RS_ASSERT("ia[3] == 0", ia[3] == 0);
+        _RS_ASSERT("ia.length == 4", ia.length == 4);
+
+        long[] la = s.get_la();
+        _RS_ASSERT("la[0] == 13", la[0] == 13);
+        _RS_ASSERT("la[1] == 21", la[1] == 21);
+        _RS_ASSERT("la.length == 4", la.length == 2);
+
+        long[] lla = s.get_lla();
+        _RS_ASSERT("lla[0] == 34", lla[0] == 34);
+        _RS_ASSERT("lla[1] == 0", lla[1] == 0);
+        _RS_ASSERT("lla[2] == 0", lla[2] == 0);
+        _RS_ASSERT("lla[3] == 0", lla[3] == 0);
+        _RS_ASSERT("lla.length == 4", lla.length == 4);
+
+        boolean[] ba = s.get_ba();
+        _RS_ASSERT("ba[0] == true", ba[0] == true);
+        _RS_ASSERT("ba[1] == false", ba[1] == false);
+        _RS_ASSERT("ba[2] == false", ba[2] == false);
+        _RS_ASSERT("ba.length == 3", ba.length == 3);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_array_init s = new ScriptC_array_init(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        checkInit(s);
+        s.invoke_array_init_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+        passTest();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_atomic.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_atomic.java
new file mode 100644
index 0000000..7fe4b36
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_atomic.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_atomic extends UnitTest {
+    private Resources mRes;
+
+    protected UT_atomic(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Atomics", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_atomic s = new ScriptC_atomic(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_atomic_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_bug_char.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_bug_char.java
new file mode 100644
index 0000000..5da5288
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_bug_char.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import java.util.Arrays;
+
+public class UT_bug_char extends UnitTest {
+    private Resources mRes;
+
+    protected UT_bug_char(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Bug Char", ctx);
+        mRes = res;
+    }
+
+    // packing functions
+    private Byte2 pack_b2(byte[] val) {
+        assert val.length == 2;
+        Log.i("bug_char", "pack_b2 " + val[0] + " " + val[1]);
+        return new Byte2(val[0], val[1]);
+    }
+
+    private byte min(byte v1, byte v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private byte[] min(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+
+    private void initializeValues(ScriptC_bug_char s) {
+        byte rand_sc1_0 = (byte)7;
+        byte[] rand_sc2_0 = new byte[2];
+        rand_sc2_0[0] = 11;
+        rand_sc2_0[1] = 21;
+        Log.i("bug_char", "Generated sc2_0 to " + Arrays.toString(rand_sc2_0));
+        byte rand_sc1_1 = (byte)10;
+        byte[] rand_sc2_1 = new byte[2];
+        rand_sc2_1[0] = 13;
+        rand_sc2_1[1] = 15;
+        Log.i("bug_char", "Generated sc2_1 to " + Arrays.toString(rand_sc2_1));
+
+        s.set_rand_sc1_0(rand_sc1_0);
+        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
+        s.set_rand_sc1_1(rand_sc1_1);
+        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
+        // Set results for min
+        s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1));
+        byte[] min_rand_sc2_raw = min(rand_sc2_0, rand_sc2_1);
+        Log.i("bug_char", "Generating min_rand_sc2_sc2 to " +
+              Arrays.toString(min_rand_sc2_raw));
+        Byte2 min_rand_sc2 = pack_b2(min_rand_sc2_raw);
+        Log.i("bug_char", "Setting min_rand_sc2_sc2 to [" + min_rand_sc2.x +
+              ", " + min_rand_sc2.y + "]");
+        s.set_min_rand_sc2_sc2(min_rand_sc2);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_bug_char s = new ScriptC_bug_char(pRS, mRes,
+                R.raw.bug_char);
+        pRS.setMessageHandler(mRsMessage);
+        initializeValues(s);
+        s.invoke_bug_char_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp.java
new file mode 100644
index 0000000..1f28abc
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_clamp extends UnitTest {
+    private Resources mRes;
+
+    protected UT_clamp(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Clamp (Full)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_clamp s = new ScriptC_clamp(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_clamp_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp_relaxed.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp_relaxed.java
new file mode 100644
index 0000000..d880e68
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp_relaxed.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_clamp_relaxed extends UnitTest {
+    private Resources mRes;
+
+    protected UT_clamp_relaxed(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Clamp (Relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_clamp_relaxed s =
+                new ScriptC_clamp_relaxed(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_clamp_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_constant.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_constant.java
new file mode 100644
index 0000000..3085032
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_constant.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_constant extends UnitTest {
+    private Resources mRes;
+
+    protected UT_constant(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Const", ctx);
+        mRes = res;
+    }
+
+    private void Assert(boolean b) {
+        if (!b) {
+            failTest();
+        }
+    }
+
+    public void run() {
+        Assert(ScriptC_constant.const_floatTest == 1.99f);
+        Assert(ScriptC_constant.const_doubleTest == 2.05);
+        Assert(ScriptC_constant.const_charTest == -8);
+        Assert(ScriptC_constant.const_shortTest == -16);
+        Assert(ScriptC_constant.const_intTest == -32);
+        Assert(ScriptC_constant.const_longTest == 17179869184l);
+        Assert(ScriptC_constant.const_longlongTest == 68719476736l);
+
+        Assert(ScriptC_constant.const_ucharTest == 8);
+        Assert(ScriptC_constant.const_ushortTest == 16);
+        Assert(ScriptC_constant.const_uintTest == 32);
+        Assert(ScriptC_constant.const_ulongTest == 4611686018427387904L);
+        Assert(ScriptC_constant.const_int64_tTest == -17179869184l);
+        Assert(ScriptC_constant.const_uint64_tTest == 117179869184l);
+
+        Assert(ScriptC_constant.const_boolTest == true);
+
+        passTest();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_convert.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_convert.java
new file mode 100644
index 0000000..a7cb226
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_convert.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_convert extends UnitTest {
+    private Resources mRes;
+
+    protected UT_convert(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Convert", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_convert s = new ScriptC_convert(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_convert_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_convert_relaxed.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_convert_relaxed.java
new file mode 100644
index 0000000..269bcef
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_convert_relaxed.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_convert_relaxed extends UnitTest {
+    private Resources mRes;
+
+    protected UT_convert_relaxed(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Convert (Relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_convert_relaxed s =
+                new ScriptC_convert_relaxed(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_convert_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_copy_test.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_copy_test.java
new file mode 100644
index 0000000..f435dde
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_copy_test.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class UT_copy_test extends UnitTest {
+    private Resources mRes;
+    boolean pass = true;
+
+    protected UT_copy_test(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Copy", ctx);
+        mRes = res;
+    }
+
+    void testFloat2(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_2(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_2(rs), 1024);
+
+        float[] f1 = new float[1024 * 2];
+        float[] f2 = new float[1024 * 2];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat2(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if (f1[ct] != f2[ct]) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    void testFloat3(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_3(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_3(rs), 1024);
+
+        float[] f1 = new float[1024 * 4];
+        float[] f2 = new float[1024 * 4];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat3(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if ((f1[ct] != f2[ct]) && ((ct&3) != 3)) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    void testFloat4(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_4(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_4(rs), 1024);
+
+        float[] f1 = new float[1024 * 4];
+        float[] f2 = new float[1024 * 4];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat4(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if (f1[ct] != f2[ct]) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_copy_test s = new ScriptC_copy_test(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        testFloat2(pRS, s);
+        testFloat3(pRS, s);
+        testFloat4(pRS, s);
+        s.invoke_sendResult(true);
+
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_element.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_element.java
new file mode 100644
index 0000000..abfa44c
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_element.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_element extends UnitTest {
+    private Resources mRes;
+
+    Element simpleElem;
+    Element complexElem;
+
+    final String subElemNames[] = {
+        "subElem0",
+        "subElem1",
+        "subElem2",
+        "arrayElem0",
+        "arrayElem1",
+        "subElem3",
+        "subElem4",
+        "subElem5",
+        "subElem6",
+        "subElem_7",
+    };
+
+    final int subElemArraySizes[] = {
+        1,
+        1,
+        1,
+        2,
+        5,
+        1,
+        1,
+        1,
+        1,
+        1,
+    };
+
+    final int subElemOffsets[] = {
+        0,
+        4,
+        8,
+        12,
+        20,
+        40,
+        44,
+        48,
+        64,
+        80,
+    };
+
+    protected UT_element(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Element", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_element s) {
+        simpleElem = Element.F32_3(RS);
+        complexElem = ScriptField_ComplexStruct.createElement(RS);
+        s.set_simpleElem(simpleElem);
+        s.set_complexElem(complexElem);
+
+        ScriptField_ComplexStruct data = new ScriptField_ComplexStruct(RS, 1);
+        s.bind_complexStruct(data);
+    }
+
+    private void testScriptSide(RenderScript pRS) {
+        ScriptC_element s = new ScriptC_element(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_element_test();
+        pRS.finish();
+        waitForMessage();
+    }
+
+    private void testJavaSide(RenderScript RS) {
+
+        int subElemCount = simpleElem.getSubElementCount();
+        _RS_ASSERT("subElemCount == 0", subElemCount == 0);
+
+        subElemCount = complexElem.getSubElementCount();
+        _RS_ASSERT("subElemCount == 10", subElemCount == 10);
+        _RS_ASSERT("complexElem.getSizeBytes() == ScriptField_ComplexStruct.Item.sizeof",
+                   complexElem.getBytesSize() == ScriptField_ComplexStruct.Item.sizeof);
+
+        for (int i = 0; i < subElemCount; i ++) {
+            _RS_ASSERT("complexElem.getSubElement(i) != null",
+                       complexElem.getSubElement(i) != null);
+            _RS_ASSERT("complexElem.getSubElementName(i).equals(subElemNames[i])",
+                       complexElem.getSubElementName(i).equals(subElemNames[i]));
+            _RS_ASSERT("complexElem.getSubElementArraySize(i) == subElemArraySizes[i]",
+                       complexElem.getSubElementArraySize(i) == subElemArraySizes[i]);
+            _RS_ASSERT("complexElem.getSubElementOffsetBytes(i) == subElemOffsets[i]",
+                       complexElem.getSubElementOffsetBytes(i) == subElemOffsets[i]);
+        }
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        testScriptSide(pRS);
+        testJavaSide(pRS);
+        passTest();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java
new file mode 100644
index 0000000..c3f3ca0
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_foreach extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_foreach(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_foreach s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_a(A);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_foreach s = new ScriptC_foreach(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_root(A);
+        s.invoke_verify_root();
+        s.forEach_foo(A, A);
+        s.invoke_verify_foo();
+        s.invoke_foreach_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java
new file mode 100644
index 0000000..653ebd5
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_foreach_bounds extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_foreach_bounds(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach (bounds)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_foreach_bounds s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_a(A);
+        s.set_s(s);
+        s.set_ain(A);
+        s.set_aout(A);
+        s.set_xStart(2);
+        s.set_xEnd(5);
+        s.set_yStart(3);
+        s.set_yEnd(6);
+        s.forEach_zero(A);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_foreach_bounds s = new ScriptC_foreach_bounds(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_foreach_bounds_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_fp_mad.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_fp_mad.java
new file mode 100644
index 0000000..960df24
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_fp_mad.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_fp_mad extends UnitTest {
+    private Resources mRes;
+
+    protected UT_fp_mad(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Fp_Mad", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_fp_mad s = new ScriptC_fp_mad(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_fp_mad_test(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_int4.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_int4.java
new file mode 100644
index 0000000..9592798
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_int4.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_int4 extends UnitTest {
+    private Resources mRes;
+
+    protected UT_int4(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "int4", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_int4 s = new ScriptC_int4(pRS, mRes, R.raw.int4);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_int4_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel.java
new file mode 100644
index 0000000..ec67665
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class UT_kernel extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+    private Allocation B;
+
+    protected UT_kernel(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Kernels (pass-by-value)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_kernel s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        s.set_dimX(X);
+        typeBuilder.setX(X);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_ain(A);
+        B = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_aout(B);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_kernel s = new ScriptC_kernel(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_init_vars(A);
+        s.forEach_root(A, B);
+        s.invoke_verify_root();
+        s.invoke_kernel_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel_struct.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel_struct.java
new file mode 100644
index 0000000..07538ec
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel_struct.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class UT_kernel_struct extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+    private Allocation B;
+
+    protected UT_kernel_struct(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Kernels (struct pass-by-value)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_kernel_struct s) {
+        int X = 5;
+        s.set_dimX(X);
+        ScriptField_simpleStruct t;
+        t = new ScriptField_simpleStruct(RS, X);
+        s.bind_ain(t);
+        A = t.getAllocation();
+        t = new ScriptField_simpleStruct(RS, X);
+        s.bind_aout(t);
+        B = t.getAllocation();
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_kernel_struct s = new ScriptC_kernel_struct(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_init_vars(A);
+        s.forEach_root(A, B);
+        s.invoke_verify_root();
+        s.invoke_kernel_struct_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math.java
new file mode 100644
index 0000000..055c454
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_math extends UnitTest {
+    private Resources mRes;
+
+    protected UT_math(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math s = new ScriptC_math(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_math_test(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math_agree.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math_agree.java
new file mode 100644
index 0000000..a7e7429
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math_agree.java
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import java.util.Arrays;
+import java.util.Random;
+
+public class UT_math_agree extends UnitTest {
+    private Resources mRes;
+    private Random rand;
+
+    protected UT_math_agree(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math Agreement", ctx);
+        mRes = res;
+        rand = new Random();
+    }
+
+    // packing functions
+    private Float2 pack_f2(float[] val) {
+        assert val.length == 2;
+        return new Float2(val[0], val[1]);
+    }
+    private Float3 pack_f3(float[] val) {
+        assert val.length == 3;
+        return new Float3(val[0], val[1], val[2]);
+    }
+    private Float4 pack_f4(float[] val) {
+        assert val.length == 4;
+        return new Float4(val[0], val[1], val[2], val[3]);
+    }
+    private Byte2 pack_b2(byte[] val) {
+        assert val.length == 2;
+        return new Byte2(val[0], val[1]);
+    }
+    private Byte3 pack_b3(byte[] val) {
+        assert val.length == 3;
+        return new Byte3(val[0], val[1], val[2]);
+    }
+    private Byte4 pack_b4(byte[] val) {
+        assert val.length == 4;
+        return new Byte4(val[0], val[1], val[2], val[3]);
+    }
+    private Short2 pack_s2(short[] val) {
+        assert val.length == 2;
+        return new Short2(val[0], val[1]);
+    }
+    private Short3 pack_s3(short[] val) {
+        assert val.length == 3;
+        return new Short3(val[0], val[1], val[2]);
+    }
+    private Short4 pack_s4(short[] val) {
+        assert val.length == 4;
+        return new Short4(val[0], val[1], val[2], val[3]);
+    }
+    private Int2 pack_i2(int[] val) {
+        assert val.length == 2;
+        return new Int2(val[0], val[1]);
+    }
+    private Int3 pack_i3(int[] val) {
+        assert val.length == 3;
+        return new Int3(val[0], val[1], val[2]);
+    }
+    private Int4 pack_i4(int[] val) {
+        assert val.length == 4;
+        return new Int4(val[0], val[1], val[2], val[3]);
+    }
+    private Long2 pack_l2(long[] val) {
+        assert val.length == 2;
+        return new Long2(val[0], val[1]);
+    }
+    private Long3 pack_l3(long[] val) {
+        assert val.length == 3;
+        return new Long3(val[0], val[1], val[2]);
+    }
+    private Long4 pack_l4(long[] val) {
+        assert val.length == 4;
+        return new Long4(val[0], val[1], val[2], val[3]);
+    }
+
+    // random vector generation functions
+    private float[] randvec_float(int dim) {
+        float[] fv = new float[dim];
+        for (int i = 0; i < dim; ++i)
+            fv[i] = rand.nextFloat();
+        return fv;
+    }
+    private byte[] randvec_char(int dim) {
+        byte[] cv = new byte[dim];
+        rand.nextBytes(cv);
+        return cv;
+    }
+    private short[] randvec_uchar(int dim) {
+       short[] ucv = new short[dim];
+       for (int i = 0; i < dim; ++i)
+           ucv[i] = (short)rand.nextInt(0x1 << 8);
+       return ucv;
+    }
+    private short[] randvec_short(int dim) {
+        short[] sv = new short[dim];
+        for (int i = 0; i < dim; ++i)
+            sv[i] = (short)rand.nextInt(0x1 << 16);
+        return sv;
+    }
+    private int[] randvec_ushort(int dim) {
+        int[] usv = new int[dim];
+        for (int i = 0; i < dim; ++i)
+            usv[i] = rand.nextInt(0x1 << 16);
+        return usv;
+    }
+    private int[] randvec_int(int dim) {
+        int[] iv = new int[dim];
+        for (int i = 0; i < dim; ++i)
+            iv[i] = rand.nextInt();
+        return iv;
+    }
+    private long[] randvec_uint(int dim) {
+        long[] uiv = new long[dim];
+        for (int i = 0; i < dim; ++i)
+            uiv[i] = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        return uiv;
+    }
+    private long[] randvec_long(int dim) {
+        long[] lv = new long[dim];
+        for (int i = 0; i < dim; ++i)
+            lv[i] = rand.nextLong();
+        return lv;
+    }
+    // TODO:  unsigned long generator
+
+    // min reference functions
+    private float min(float v1, float v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private float[] min(float[] v1, float[] v2) {
+        assert v1.length == v2.length;
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private byte min(byte v1, byte v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private byte[] min(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private short min(short v1, short v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private short[] min(short[] v1, short[] v2) {
+        assert v1.length == v2.length;
+        short[] rv = new short[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private int min(int v1, int v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private int[] min(int[] v1, int[] v2) {
+        assert v1.length == v2.length;
+        int[] rv = new int[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private long min(long v1, long v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private long[] min(long[] v1, long[] v2) {
+        assert v1.length == v2.length;
+        long[] rv = new long[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    // TODO:  unsigned long version of min
+
+    // max reference functions
+    private float max(float v1, float v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private float[] max(float[] v1, float[] v2) {
+        assert v1.length == v2.length;
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private byte max(byte v1, byte v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private byte[] max(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private short max(short v1, short v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private short[] max(short[] v1, short[] v2) {
+        assert v1.length == v2.length;
+        short[] rv = new short[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private int max(int v1, int v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private int[] max(int[] v1, int[] v2) {
+        assert v1.length == v2.length;
+        int[] rv = new int[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private long max(long v1, long v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private long[] max(long[] v1, long[] v2) {
+        assert v1.length == v2.length;
+        long[] rv = new long[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    // TODO:  unsigned long version of max
+
+    // fmin reference functions
+    private float fmin(float v1, float v2) {
+        return min(v1, v2);
+    }
+    private float[] fmin(float[] v1, float[] v2) {
+        return min(v1, v2);
+    }
+    private float[] fmin(float[] v1, float v2) {
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2);
+        return rv;
+    }
+
+    // fmax reference functions
+    private float fmax(float v1, float v2) {
+        return max(v1, v2);
+    }
+    private float[] fmax(float[] v1, float[] v2) {
+        return max(v1, v2);
+    }
+    private float[] fmax(float[] v1, float v2) {
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2);
+        return rv;
+    }
+
+    private void initializeValues(ScriptC_math_agree s) {
+        float x = rand.nextFloat();
+        float y = rand.nextFloat();
+
+        s.set_x(x);
+        s.set_y(y);
+        s.set_result_add(x + y);
+        s.set_result_sub(x - y);
+        s.set_result_mul(x * y);
+        s.set_result_div(x / y);
+
+        // Generate random vectors of all types
+        float rand_f1_0 = rand.nextFloat();
+        float[] rand_f2_0 = randvec_float(2);
+        float[] rand_f3_0 = randvec_float(3);
+        float[] rand_f4_0 = randvec_float(4);
+        float rand_f1_1 = rand.nextFloat();
+        float[] rand_f2_1 = randvec_float(2);
+        float[] rand_f3_1 = randvec_float(3);
+        float[] rand_f4_1 = randvec_float(4);
+        short rand_uc1_0 = (short)rand.nextInt(0x1 << 8);
+        short[] rand_uc2_0 = randvec_uchar(2);
+        short[] rand_uc3_0 = randvec_uchar(3);
+        short[] rand_uc4_0 = randvec_uchar(4);
+        short rand_uc1_1 = (short)rand.nextInt(0x1 << 8);
+        short[] rand_uc2_1 = randvec_uchar(2);
+        short[] rand_uc3_1 = randvec_uchar(3);
+        short[] rand_uc4_1 = randvec_uchar(4);
+        short rand_ss1_0 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_0 = randvec_short(2);
+        short[] rand_ss3_0 = randvec_short(3);
+        short[] rand_ss4_0 = randvec_short(4);
+        short rand_ss1_1 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_1 = randvec_short(2);
+        short[] rand_ss3_1 = randvec_short(3);
+        short[] rand_ss4_1 = randvec_short(4);
+        int rand_us1_0 = rand.nextInt(0x1 << 16);
+        int[] rand_us2_0 = randvec_ushort(2);
+        int[] rand_us3_0 = randvec_ushort(3);
+        int[] rand_us4_0 = randvec_ushort(4);
+        int rand_us1_1 = rand.nextInt(0x1 << 16);
+        int[] rand_us2_1 = randvec_ushort(2);
+        int[] rand_us3_1 = randvec_ushort(3);
+        int[] rand_us4_1 = randvec_ushort(4);
+        int rand_si1_0 = rand.nextInt();
+        int[] rand_si2_0 = randvec_int(2);
+        int[] rand_si3_0 = randvec_int(3);
+        int[] rand_si4_0 = randvec_int(4);
+        int rand_si1_1 = rand.nextInt();
+        int[] rand_si2_1 = randvec_int(2);
+        int[] rand_si3_1 = randvec_int(3);
+        int[] rand_si4_1 = randvec_int(4);
+        long rand_ui1_0 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        long[] rand_ui2_0 = randvec_uint(2);
+        long[] rand_ui3_0 = randvec_uint(3);
+        long[] rand_ui4_0 = randvec_uint(4);
+        long rand_ui1_1 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        long[] rand_ui2_1 = randvec_uint(2);
+        long[] rand_ui3_1 = randvec_uint(3);
+        long[] rand_ui4_1 = randvec_uint(4);
+        long rand_sl1_0 = rand.nextLong();
+        long[] rand_sl2_0 = randvec_long(2);
+        long[] rand_sl3_0 = randvec_long(3);
+        long[] rand_sl4_0 = randvec_long(4);
+        long rand_sl1_1 = rand.nextLong();
+        long[] rand_sl2_1 = randvec_long(2);
+        long[] rand_sl3_1 = randvec_long(3);
+        long[] rand_sl4_1 = randvec_long(4);
+        byte rand_sc1_0 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_0 = randvec_char(2);
+        byte[] rand_sc3_0 = randvec_char(3);
+        byte[] rand_sc4_0 = randvec_char(4);
+        byte rand_sc1_1 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_1 = randvec_char(2);
+        byte[] rand_sc3_1 = randvec_char(3);
+        byte[] rand_sc4_1 = randvec_char(4);
+        // TODO:  generate unsigned long vectors
+
+        // Set random vectors in renderscript code
+        s.set_rand_f1_0(rand_f1_0);
+        s.set_rand_f2_0(pack_f2(rand_f2_0));
+        s.set_rand_f3_0(pack_f3(rand_f3_0));
+        s.set_rand_f4_0(pack_f4(rand_f4_0));
+        s.set_rand_f1_1(rand_f1_1);
+        s.set_rand_f2_1(pack_f2(rand_f2_1));
+        s.set_rand_f3_1(pack_f3(rand_f3_1));
+        s.set_rand_f4_1(pack_f4(rand_f4_1));
+        s.set_rand_uc1_1(rand_uc1_1);
+        s.set_rand_uc2_1(pack_s2(rand_uc2_1));
+        s.set_rand_uc3_1(pack_s3(rand_uc3_1));
+        s.set_rand_uc4_1(pack_s4(rand_uc4_1));
+        s.set_rand_ss1_0(rand_ss1_0);
+        s.set_rand_ss2_0(pack_s2(rand_ss2_0));
+        s.set_rand_ss3_0(pack_s3(rand_ss3_0));
+        s.set_rand_ss4_0(pack_s4(rand_ss4_0));
+        s.set_rand_ss1_1(rand_ss1_1);
+        s.set_rand_ss2_1(pack_s2(rand_ss2_1));
+        s.set_rand_ss3_1(pack_s3(rand_ss3_1));
+        s.set_rand_ss4_1(pack_s4(rand_ss4_1));
+        s.set_rand_us1_0(rand_us1_0);
+        s.set_rand_us2_0(pack_i2(rand_us2_0));
+        s.set_rand_us3_0(pack_i3(rand_us3_0));
+        s.set_rand_us4_0(pack_i4(rand_us4_0));
+        s.set_rand_us1_1(rand_us1_1);
+        s.set_rand_us2_1(pack_i2(rand_us2_1));
+        s.set_rand_us3_1(pack_i3(rand_us3_1));
+        s.set_rand_us4_1(pack_i4(rand_us4_1));
+        s.set_rand_si1_0(rand_si1_0);
+        s.set_rand_si2_0(pack_i2(rand_si2_0));
+        s.set_rand_si3_0(pack_i3(rand_si3_0));
+        s.set_rand_si4_0(pack_i4(rand_si4_0));
+        s.set_rand_si1_1(rand_si1_1);
+        s.set_rand_si2_1(pack_i2(rand_si2_1));
+        s.set_rand_si3_1(pack_i3(rand_si3_1));
+        s.set_rand_si4_1(pack_i4(rand_si4_1));
+        s.set_rand_ui1_0(rand_ui1_0);
+        s.set_rand_ui2_0(pack_l2(rand_ui2_0));
+        s.set_rand_ui3_0(pack_l3(rand_ui3_0));
+        s.set_rand_ui4_0(pack_l4(rand_ui4_0));
+        s.set_rand_ui1_1(rand_ui1_1);
+        s.set_rand_ui2_1(pack_l2(rand_ui2_1));
+        s.set_rand_ui3_1(pack_l3(rand_ui3_1));
+        s.set_rand_ui4_1(pack_l4(rand_ui4_1));
+        s.set_rand_sl1_0(rand_sl1_0);
+        s.set_rand_sl2_0(pack_l2(rand_sl2_0));
+        s.set_rand_sl3_0(pack_l3(rand_sl3_0));
+        s.set_rand_sl4_0(pack_l4(rand_sl4_0));
+        s.set_rand_sl1_1(rand_sl1_1);
+        s.set_rand_sl2_1(pack_l2(rand_sl2_1));
+        s.set_rand_sl3_1(pack_l3(rand_sl3_1));
+        s.set_rand_sl4_1(pack_l4(rand_sl4_1));
+        s.set_rand_uc1_0(rand_uc1_0);
+        s.set_rand_uc2_0(pack_s2(rand_uc2_0));
+        s.set_rand_uc3_0(pack_s3(rand_uc3_0));
+        s.set_rand_uc4_0(pack_s4(rand_uc4_0));
+        s.set_rand_sc1_0(rand_sc1_0);
+        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
+        s.set_rand_sc3_0(pack_b3(rand_sc3_0));
+        s.set_rand_sc4_0(pack_b4(rand_sc4_0));
+        s.set_rand_sc1_1(rand_sc1_1);
+        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
+        s.set_rand_sc3_1(pack_b3(rand_sc3_1));
+        s.set_rand_sc4_1(pack_b4(rand_sc4_1));
+        // TODO:  set unsigned long vectors
+
+        // Set results for min
+        s.set_min_rand_f1_f1(min(rand_f1_0, rand_f1_1));
+        s.set_min_rand_f2_f2(pack_f2(min(rand_f2_0, rand_f2_1)));
+        s.set_min_rand_f3_f3(pack_f3(min(rand_f3_0, rand_f3_1)));
+        s.set_min_rand_f4_f4(pack_f4(min(rand_f4_0, rand_f4_1)));
+        s.set_min_rand_uc1_uc1(min(rand_uc1_0, rand_uc1_1));
+        s.set_min_rand_uc2_uc2(pack_s2(min(rand_uc2_0, rand_uc2_1)));
+        s.set_min_rand_uc3_uc3(pack_s3(min(rand_uc3_0, rand_uc3_1)));
+        s.set_min_rand_uc4_uc4(pack_s4(min(rand_uc4_0, rand_uc4_1)));
+        s.set_min_rand_ss1_ss1(min(rand_ss1_0, rand_ss1_1));
+        s.set_min_rand_ss2_ss2(pack_s2(min(rand_ss2_0, rand_ss2_1)));
+        s.set_min_rand_ss3_ss3(pack_s3(min(rand_ss3_0, rand_ss3_1)));
+        s.set_min_rand_ss4_ss4(pack_s4(min(rand_ss4_0, rand_ss4_1)));
+        s.set_min_rand_us1_us1(min(rand_us1_0, rand_us1_1));
+        s.set_min_rand_us2_us2(pack_i2(min(rand_us2_0, rand_us2_1)));
+        s.set_min_rand_us3_us3(pack_i3(min(rand_us3_0, rand_us3_1)));
+        s.set_min_rand_us4_us4(pack_i4(min(rand_us4_0, rand_us4_1)));
+        s.set_min_rand_si1_si1(min(rand_si1_0, rand_si1_1));
+        s.set_min_rand_si2_si2(pack_i2(min(rand_si2_0, rand_si2_1)));
+        s.set_min_rand_si3_si3(pack_i3(min(rand_si3_0, rand_si3_1)));
+        s.set_min_rand_si4_si4(pack_i4(min(rand_si4_0, rand_si4_1)));
+        s.set_min_rand_ui1_ui1(min(rand_ui1_0, rand_ui1_1));
+        s.set_min_rand_ui2_ui2(pack_l2(min(rand_ui2_0, rand_ui2_1)));
+        s.set_min_rand_ui3_ui3(pack_l3(min(rand_ui3_0, rand_ui3_1)));
+        s.set_min_rand_ui4_ui4(pack_l4(min(rand_ui4_0, rand_ui4_1)));
+        s.set_min_rand_sl1_sl1(min(rand_sl1_0, rand_sl1_1));
+        s.set_min_rand_sl2_sl2(pack_l2(min(rand_sl2_0, rand_sl2_1)));
+        s.set_min_rand_sl3_sl3(pack_l3(min(rand_sl3_0, rand_sl3_1)));
+        s.set_min_rand_sl4_sl4(pack_l4(min(rand_sl4_0, rand_sl4_1)));
+        s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1));
+        s.set_min_rand_sc2_sc2(pack_b2(min(rand_sc2_0, rand_sc2_1)));
+        s.set_min_rand_sc3_sc3(pack_b3(min(rand_sc3_0, rand_sc3_1)));
+        s.set_min_rand_sc4_sc4(pack_b4(min(rand_sc4_0, rand_sc4_1)));
+        // TODO:  set results for unsigned long min
+
+        // Set results for max
+        s.set_max_rand_f1_f1(max(rand_f1_0, rand_f1_1));
+        s.set_max_rand_f2_f2(pack_f2(max(rand_f2_0, rand_f2_1)));
+        s.set_max_rand_f3_f3(pack_f3(max(rand_f3_0, rand_f3_1)));
+        s.set_max_rand_f4_f4(pack_f4(max(rand_f4_0, rand_f4_1)));
+        s.set_max_rand_uc1_uc1(max(rand_uc1_0, rand_uc1_1));
+        s.set_max_rand_uc2_uc2(pack_s2(max(rand_uc2_0, rand_uc2_1)));
+        s.set_max_rand_uc3_uc3(pack_s3(max(rand_uc3_0, rand_uc3_1)));
+        s.set_max_rand_uc4_uc4(pack_s4(max(rand_uc4_0, rand_uc4_1)));
+        s.set_max_rand_ss1_ss1(max(rand_ss1_0, rand_ss1_1));
+        s.set_max_rand_ss2_ss2(pack_s2(max(rand_ss2_0, rand_ss2_1)));
+        s.set_max_rand_ss3_ss3(pack_s3(max(rand_ss3_0, rand_ss3_1)));
+        s.set_max_rand_ss4_ss4(pack_s4(max(rand_ss4_0, rand_ss4_1)));
+        s.set_max_rand_us1_us1(max(rand_us1_0, rand_us1_1));
+        s.set_max_rand_us2_us2(pack_i2(max(rand_us2_0, rand_us2_1)));
+        s.set_max_rand_us3_us3(pack_i3(max(rand_us3_0, rand_us3_1)));
+        s.set_max_rand_us4_us4(pack_i4(max(rand_us4_0, rand_us4_1)));
+        s.set_max_rand_si1_si1(max(rand_si1_0, rand_si1_1));
+        s.set_max_rand_si2_si2(pack_i2(max(rand_si2_0, rand_si2_1)));
+        s.set_max_rand_si3_si3(pack_i3(max(rand_si3_0, rand_si3_1)));
+        s.set_max_rand_si4_si4(pack_i4(max(rand_si4_0, rand_si4_1)));
+        s.set_max_rand_ui1_ui1(max(rand_ui1_0, rand_ui1_1));
+        s.set_max_rand_ui2_ui2(pack_l2(max(rand_ui2_0, rand_ui2_1)));
+        s.set_max_rand_ui3_ui3(pack_l3(max(rand_ui3_0, rand_ui3_1)));
+        s.set_max_rand_ui4_ui4(pack_l4(max(rand_ui4_0, rand_ui4_1)));
+        s.set_max_rand_sl1_sl1(max(rand_sl1_0, rand_sl1_1));
+        s.set_max_rand_sl2_sl2(pack_l2(max(rand_sl2_0, rand_sl2_1)));
+        s.set_max_rand_sl3_sl3(pack_l3(max(rand_sl3_0, rand_sl3_1)));
+        s.set_max_rand_sl4_sl4(pack_l4(max(rand_sl4_0, rand_sl4_1)));
+        s.set_max_rand_sc1_sc1(max(rand_sc1_0, rand_sc1_1));
+        s.set_max_rand_sc2_sc2(pack_b2(max(rand_sc2_0, rand_sc2_1)));
+        s.set_max_rand_sc3_sc3(pack_b3(max(rand_sc3_0, rand_sc3_1)));
+        s.set_max_rand_sc4_sc4(pack_b4(max(rand_sc4_0, rand_sc4_1)));
+
+        // TODO:  set results for unsigned long max
+
+        // Set results for fmin
+        s.set_fmin_rand_f1_f1(fmin(rand_f1_0, rand_f1_1));
+        s.set_fmin_rand_f2_f2(pack_f2(fmin(rand_f2_0, rand_f2_1)));
+        s.set_fmin_rand_f3_f3(pack_f3(fmin(rand_f3_0, rand_f3_1)));
+        s.set_fmin_rand_f4_f4(pack_f4(fmin(rand_f4_0, rand_f4_1)));
+        s.set_fmin_rand_f2_f1(pack_f2(fmin(rand_f2_0, rand_f1_1)));
+        s.set_fmin_rand_f3_f1(pack_f3(fmin(rand_f3_0, rand_f1_1)));
+        s.set_fmin_rand_f4_f1(pack_f4(fmin(rand_f4_0, rand_f1_1)));
+
+        // Set results for fmax
+        s.set_fmax_rand_f1_f1(fmax(rand_f1_0, rand_f1_1));
+        s.set_fmax_rand_f2_f2(pack_f2(fmax(rand_f2_0, rand_f2_1)));
+        s.set_fmax_rand_f3_f3(pack_f3(fmax(rand_f3_0, rand_f3_1)));
+        s.set_fmax_rand_f4_f4(pack_f4(fmax(rand_f4_0, rand_f4_1)));
+        s.set_fmax_rand_f2_f1(pack_f2(fmax(rand_f2_0, rand_f1_1)));
+        s.set_fmax_rand_f3_f1(pack_f3(fmax(rand_f3_0, rand_f1_1)));
+        s.set_fmax_rand_f4_f1(pack_f4(fmax(rand_f4_0, rand_f1_1)));
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math_agree s = new ScriptC_math_agree(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeValues(s);
+        s.invoke_math_agree_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math_conformance.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math_conformance.java
new file mode 100644
index 0000000..384cd13
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math_conformance.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_math_conformance extends UnitTest {
+    private Resources mRes;
+
+    protected UT_math_conformance(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math Conformance", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math_conformance s =
+                new ScriptC_math_conformance(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_math_conformance_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+        passTest();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_min.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_min.java
new file mode 100644
index 0000000..cea9fe5
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_min.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_min extends UnitTest {
+    private Resources mRes;
+
+    protected UT_min(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Min (relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_min s = new ScriptC_min(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_min_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java
new file mode 100644
index 0000000..69fc97f
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_noroot extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_noroot(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach (no root)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_noroot s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_a(A);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_noroot s = new ScriptC_noroot(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_foo(A, A);
+        s.invoke_verify_foo();
+        s.invoke_noroot_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_primitives.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_primitives.java
new file mode 100644
index 0000000..3c663a8
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_primitives.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_primitives extends UnitTest {
+    private Resources mRes;
+
+    protected UT_primitives(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Primitives", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_primitives s) {
+        float pF = s.get_floatTest();
+        if (pF != 1.99f) {
+            return false;
+        }
+        s.set_floatTest(2.99f);
+
+        double pD = s.get_doubleTest();
+        if (pD != 2.05) {
+            return false;
+        }
+        s.set_doubleTest(3.05);
+
+        byte pC = s.get_charTest();
+        if (pC != -8) {
+            return false;
+        }
+        s.set_charTest((byte)-16);
+
+        short pS = s.get_shortTest();
+        if (pS != -16) {
+            return false;
+        }
+        s.set_shortTest((short)-32);
+
+        int pI = s.get_intTest();
+        if (pI != -32) {
+            return false;
+        }
+        s.set_intTest(-64);
+
+        long pL = s.get_longTest();
+        if (pL != 17179869184l) {
+            return false;
+        }
+        s.set_longTest(17179869185l);
+
+        long puL = s.get_ulongTest();
+        if (puL != 4611686018427387904L) {
+            return false;
+        }
+        s.set_ulongTest(4611686018427387903L);
+
+
+        long pLL = s.get_longlongTest();
+        if (pLL != 68719476736L) {
+            return false;
+        }
+        s.set_longlongTest(68719476735L);
+
+        long pu64 = s.get_uint64_tTest();
+        if (pu64 != 117179869184l) {
+            return false;
+        }
+        s.set_uint64_tTest(117179869185l);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_primitives s = new ScriptC_primitives(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_primitives_test(0, 0);
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_refcount.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_refcount.java
new file mode 100644
index 0000000..e6317d5
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_refcount.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_refcount extends UnitTest {
+    private Resources mRes;
+
+    protected UT_refcount(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Refcount", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_refcount s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 500;
+        int Y = 700;
+        typeBuilder.setX(X).setY(Y);
+        Allocation A = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_globalA(A);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        pRS.setMessageHandler(mRsMessage);
+        ScriptC_refcount s = new ScriptC_refcount(pRS);
+        initializeGlobals(pRS, s);
+        s.invoke_refcount_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rsdebug.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rsdebug.java
new file mode 100644
index 0000000..740180e
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rsdebug.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_rsdebug extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rsdebug(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsDebug", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rsdebug s = new ScriptC_rsdebug(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rsdebug(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rstime.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rstime.java
new file mode 100644
index 0000000..86e35a8
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rstime.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_rstime extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstime(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTime", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstime s = new ScriptC_rstime(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.setTimeZone("America/Los_Angeles");
+        s.invoke_test_rstime(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rstypes.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rstypes.java
new file mode 100644
index 0000000..3245eca
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rstypes.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_rstypes extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstypes(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTypes", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstypes s = new ScriptC_rstypes(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rstypes(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_sampler.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_sampler.java
new file mode 100644
index 0000000..d8d5a78
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_sampler.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_sampler extends UnitTest {
+    private Resources mRes;
+
+    Sampler minification;
+    Sampler magnification;
+    Sampler wrapS;
+    Sampler wrapT;
+    Sampler anisotropy;
+
+    protected UT_sampler(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Sampler", ctx);
+        mRes = res;
+    }
+
+    private Sampler.Builder getDefaultBuilder(RenderScript RS) {
+        Sampler.Builder b = new Sampler.Builder(RS);
+        b.setMinification(Sampler.Value.NEAREST);
+        b.setMagnification(Sampler.Value.NEAREST);
+        b.setWrapS(Sampler.Value.CLAMP);
+        b.setWrapT(Sampler.Value.CLAMP);
+        b.setAnisotropy(1.0f);
+        return b;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_sampler s) {
+        Sampler.Builder b = getDefaultBuilder(RS);
+        b.setMinification(Sampler.Value.LINEAR_MIP_LINEAR);
+        minification = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setMagnification(Sampler.Value.LINEAR);
+        magnification = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setWrapS(Sampler.Value.WRAP);
+        wrapS = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setWrapT(Sampler.Value.WRAP);
+        wrapT = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setAnisotropy(8.0f);
+        anisotropy = b.create();
+
+        s.set_minification(minification);
+        s.set_magnification(magnification);
+        s.set_wrapS(wrapS);
+        s.set_wrapT(wrapT);
+        s.set_anisotropy(anisotropy);
+    }
+
+    private void testScriptSide(RenderScript pRS) {
+        ScriptC_sampler s = new ScriptC_sampler(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_sampler_test();
+        pRS.finish();
+        waitForMessage();
+    }
+
+    private void testJavaSide(RenderScript RS) {
+        _RS_ASSERT("minification.getMagnification() == Sampler.Value.NEAREST",
+                    minification.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("minification.getMinification() == Sampler.Value.LINEAR_MIP_LINEAR",
+                    minification.getMinification() == Sampler.Value.LINEAR_MIP_LINEAR);
+        _RS_ASSERT("minification.getWrapS() == Sampler.Value.CLAMP",
+                    minification.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("minification.getWrapT() == Sampler.Value.CLAMP",
+                    minification.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("minification.getAnisotropy() == 1.0f",
+                    minification.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("magnification.getMagnification() == Sampler.Value.LINEAR",
+                    magnification.getMagnification() == Sampler.Value.LINEAR);
+        _RS_ASSERT("magnification.getMinification() == Sampler.Value.NEAREST",
+                    magnification.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("magnification.getWrapS() == Sampler.Value.CLAMP",
+                    magnification.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("magnification.getWrapT() == Sampler.Value.CLAMP",
+                    magnification.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("magnification.getAnisotropy() == 1.0f",
+                    magnification.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("wrapS.getMagnification() == Sampler.Value.NEAREST",
+                    wrapS.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapS.getMinification() == Sampler.Value.NEAREST",
+                    wrapS.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapS.getWrapS() == Sampler.Value.WRAP",
+                    wrapS.getWrapS() == Sampler.Value.WRAP);
+        _RS_ASSERT("wrapS.getWrapT() == Sampler.Value.CLAMP",
+                    wrapS.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("wrapS.getAnisotropy() == 1.0f",
+                    wrapS.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("wrapT.getMagnification() == Sampler.Value.NEAREST",
+                    wrapT.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapT.getMinification() == Sampler.Value.NEAREST",
+                    wrapT.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapT.getWrapS() == Sampler.Value.CLAMP",
+                    wrapT.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("wrapT.getWrapT() == Sampler.Value.WRAP",
+                    wrapT.getWrapT() == Sampler.Value.WRAP);
+        _RS_ASSERT("wrapT.getAnisotropy() == 1.0f",
+                    wrapT.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("anisotropy.getMagnification() == Sampler.Value.NEAREST",
+                    anisotropy.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("anisotropy.getMinification() == Sampler.Value.NEAREST",
+                    anisotropy.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("anisotropy.getWrapS() == Sampler.Value.CLAMP",
+                    anisotropy.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("anisotropy.getWrapT() == Sampler.Value.CLAMP",
+                    anisotropy.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("anisotropy.getAnisotropy() == 1.0f",
+                    anisotropy.getAnisotropy() == 8.0f);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        testScriptSide(pRS);
+        testJavaSide(pRS);
+        passTest();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_struct.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_struct.java
new file mode 100644
index 0000000..43bbaf7
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_struct.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_struct extends UnitTest {
+    private Resources mRes;
+
+    protected UT_struct(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Struct", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_struct s = new ScriptC_struct(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        ScriptField_Point2 p = new ScriptField_Point2(pRS, 1);
+        ScriptField_Point2.Item i = new ScriptField_Point2.Item();
+        int val = 100;
+        i.x = val;
+        i.y = val;
+        p.set(i, 0, true);
+        s.bind_point2(p);
+        s.invoke_struct_test(val);
+        pRS.finish();
+        waitForMessage();
+
+        val = 200;
+        p.set_x(0, val, true);
+        p.set_y(0, val, true);
+        s.invoke_struct_test(val);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_unsigned.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_unsigned.java
new file mode 100644
index 0000000..0e16240
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_unsigned.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_unsigned extends UnitTest {
+    private Resources mRes;
+
+    protected UT_unsigned(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Unsigned", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_unsigned s) {
+        short pUC = s.get_uc();
+        if (pUC != 5) {
+            return false;
+        }
+        s.set_uc((short)129);
+
+        long pUI = s.get_ui();
+        if (pUI != 37) {
+            return false;
+        }
+        s.set_ui(0x7fffffff);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_unsigned s = new ScriptC_unsigned(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_unsigned_test();
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_vector.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_vector.java
new file mode 100644
index 0000000..6ba822e
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_vector.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_vector extends UnitTest {
+    private Resources mRes;
+
+    protected UT_vector(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Vector", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_vector s) {
+        Float2 F2 = s.get_f2();
+        if (F2.x != 1.0f || F2.y != 2.0f) {
+            return false;
+        }
+        F2.x = 2.99f;
+        F2.y = 3.99f;
+        s.set_f2(F2);
+
+        Float3 F3 = s.get_f3();
+        if (F3.x != 1.0f || F3.y != 2.0f || F3.z != 3.0f) {
+            return false;
+        }
+        F3.x = 2.99f;
+        F3.y = 3.99f;
+        F3.z = 4.99f;
+        s.set_f3(F3);
+
+        Float4 F4 = s.get_f4();
+        if (F4.x != 1.0f || F4.y != 2.0f || F4.z != 3.0f || F4.w != 4.0f) {
+            return false;
+        }
+        F4.x = 2.99f;
+        F4.y = 3.99f;
+        F4.z = 4.99f;
+        F4.w = 5.99f;
+        s.set_f4(F4);
+
+        Double2 D2 = s.get_d2();
+        if (D2.x != 1.0 || D2.y != 2.0) {
+            return false;
+        }
+        D2.x = 2.99;
+        D2.y = 3.99;
+        s.set_d2(D2);
+
+        Double3 D3 = s.get_d3();
+        if (D3.x != 1.0 || D3.y != 2.0 || D3.z != 3.0) {
+            return false;
+        }
+        D3.x = 2.99;
+        D3.y = 3.99;
+        D3.z = 4.99;
+        s.set_d3(D3);
+
+        Double4 D4 = s.get_d4();
+        if (D4.x != 1.0 || D4.y != 2.0 || D4.z != 3.0 || D4.w != 4.0) {
+            return false;
+        }
+        D4.x = 2.99;
+        D4.y = 3.99;
+        D4.z = 4.99;
+        D4.w = 5.99;
+        s.set_d4(D4);
+
+        Byte2 B2 = s.get_i8_2();
+        if (B2.x != 1 || B2.y != 2) {
+            return false;
+        }
+        B2.x = 2;
+        B2.y = 3;
+        s.set_i8_2(B2);
+
+        Byte3 B3 = s.get_i8_3();
+        if (B3.x != 1 || B3.y != 2 || B3.z != 3) {
+            return false;
+        }
+        B3.x = 2;
+        B3.y = 3;
+        B3.z = 4;
+        s.set_i8_3(B3);
+
+        Byte4 B4 = s.get_i8_4();
+        if (B4.x != 1 || B4.y != 2 || B4.z != 3 || B4.w != 4) {
+            return false;
+        }
+        B4.x = 2;
+        B4.y = 3;
+        B4.z = 4;
+        B4.w = 5;
+        s.set_i8_4(B4);
+
+        Short2 S2 = s.get_u8_2();
+        if (S2.x != 1 || S2.y != 2) {
+            return false;
+        }
+        S2.x = 2;
+        S2.y = 3;
+        s.set_u8_2(S2);
+
+        Short3 S3 = s.get_u8_3();
+        if (S3.x != 1 || S3.y != 2 || S3.z != 3) {
+            return false;
+        }
+        S3.x = 2;
+        S3.y = 3;
+        S3.z = 4;
+        s.set_u8_3(S3);
+
+        Short4 S4 = s.get_u8_4();
+        if (S4.x != 1 || S4.y != 2 || S4.z != 3 || S4.w != 4) {
+            return false;
+        }
+        S4.x = 2;
+        S4.y = 3;
+        S4.z = 4;
+        S4.w = 5;
+        s.set_u8_4(S4);
+
+        S2 = s.get_i16_2();
+        if (S2.x != 1 || S2.y != 2) {
+            return false;
+        }
+        S2.x = 2;
+        S2.y = 3;
+        s.set_i16_2(S2);
+
+        S3 = s.get_i16_3();
+        if (S3.x != 1 || S3.y != 2 || S3.z != 3) {
+            return false;
+        }
+        S3.x = 2;
+        S3.y = 3;
+        S3.z = 4;
+        s.set_i16_3(S3);
+
+        S4 = s.get_i16_4();
+        if (S4.x != 1 || S4.y != 2 || S4.z != 3 || S4.w != 4) {
+            return false;
+        }
+        S4.x = 2;
+        S4.y = 3;
+        S4.z = 4;
+        S4.w = 5;
+        s.set_i16_4(S4);
+
+        Int2 I2 = s.get_u16_2();
+        if (I2.x != 1 || I2.y != 2) {
+            return false;
+        }
+        I2.x = 2;
+        I2.y = 3;
+        s.set_u16_2(I2);
+
+        Int3 I3 = s.get_u16_3();
+        if (I3.x != 1 || I3.y != 2 || I3.z != 3) {
+            return false;
+        }
+        I3.x = 2;
+        I3.y = 3;
+        I3.z = 4;
+        s.set_u16_3(I3);
+
+        Int4 I4 = s.get_u16_4();
+        if (I4.x != 1 || I4.y != 2 || I4.z != 3 || I4.w != 4) {
+            return false;
+        }
+        I4.x = 2;
+        I4.y = 3;
+        I4.z = 4;
+        I4.w = 5;
+        s.set_u16_4(I4);
+
+        I2 = s.get_i32_2();
+        if (I2.x != 1 || I2.y != 2) {
+            return false;
+        }
+        I2.x = 2;
+        I2.y = 3;
+        s.set_i32_2(I2);
+
+        I3 = s.get_i32_3();
+        if (I3.x != 1 || I3.y != 2 || I3.z != 3) {
+            return false;
+        }
+        I3.x = 2;
+        I3.y = 3;
+        I3.z = 4;
+        s.set_i32_3(I3);
+
+        I4 = s.get_i32_4();
+        if (I4.x != 1 || I4.y != 2 || I4.z != 3 || I4.w != 4) {
+            return false;
+        }
+        I4.x = 2;
+        I4.y = 3;
+        I4.z = 4;
+        I4.w = 5;
+        s.set_i32_4(I4);
+
+        Long2 L2 = s.get_u32_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_u32_2(L2);
+
+        Long3 L3 = s.get_u32_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_u32_3(L3);
+
+        Long4 L4 = s.get_u32_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_u32_4(L4);
+
+        L2 = s.get_i64_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_i64_2(L2);
+
+        L3 = s.get_i64_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_i64_3(L3);
+
+        L4 = s.get_i64_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_i64_4(L4);
+
+        L2 = s.get_u64_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_u64_2(L2);
+
+        L3 = s.get_u64_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_u64_3(L3);
+
+        L4 = s.get_u64_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_u64_4(L4);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_vector s = new ScriptC_vector(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_vector_test();
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UnitTest.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UnitTest.java
new file mode 100644
index 0000000..01abf2f
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UnitTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+import android.content.Context;
+import android.util.Log;
+import android.support.v8.renderscript.RenderScript.RSMessageHandler;
+
+public class UnitTest extends Thread {
+    public String name;
+    private int result;
+    private ScriptField_ListAllocs_s.Item mItem;
+    private RSTestCore mRSTC;
+    private boolean msgHandled;
+    protected Context mCtx;
+
+    /* These constants must match those in shared.rsh */
+    public static final int RS_MSG_TEST_PASSED = 100;
+    public static final int RS_MSG_TEST_FAILED = 101;
+
+    private static int numTests = 0;
+    public int testID;
+
+    protected UnitTest(RSTestCore rstc, String n, int initResult, Context ctx) {
+        super();
+        mRSTC = rstc;
+        name = n;
+        msgHandled = false;
+        mCtx = ctx;
+        result = initResult;
+        testID = numTests++;
+    }
+
+    protected UnitTest(RSTestCore rstc, String n, Context ctx) {
+        this(rstc, n, 0, ctx);
+    }
+
+    protected UnitTest(RSTestCore rstc, Context ctx) {
+        this (rstc, "<Unknown>", ctx);
+    }
+
+    protected UnitTest(Context ctx) {
+        this (null, ctx);
+    }
+
+    protected void _RS_ASSERT(String message, boolean b) {
+        if(b == false) {
+            Log.e(name, message + " FAILED");
+            failTest();
+        }
+    }
+
+    private void updateUI() {
+        if (mItem != null) {
+            mItem.result = result;
+            msgHandled = true;
+            try {
+                mRSTC.refreshTestResults();
+            }
+            catch (IllegalStateException e) {
+                /* Ignore the case where our message receiver has been
+                   disconnected. This happens when we leave the application
+                   before it finishes running all of the unit tests. */
+            }
+        }
+    }
+
+    protected RSMessageHandler mRsMessage = new RSMessageHandler() {
+        public void run() {
+            if (result == 0) {
+                switch (mID) {
+                    case RS_MSG_TEST_PASSED:
+                        result = 1;
+                        break;
+                    case RS_MSG_TEST_FAILED:
+                        result = -1;
+                        break;
+                    default:
+                        RSTest.log("Unit test got unexpected message");
+                        return;
+                }
+            }
+
+            updateUI();
+        }
+    };
+
+    public void waitForMessage() {
+        while (!msgHandled) {
+            yield();
+        }
+    }
+
+    public int getResult() {
+        return result;
+    }
+
+    public void failTest() {
+        result = -1;
+        updateUI();
+    }
+
+    public void passTest() {
+        if (result != -1) {
+            result = 1;
+        }
+        updateUI();
+    }
+
+    public String toString() {
+        String out = name;
+        if (result == 1) {
+            out += " - PASSED";
+        }
+        else if (result == -1) {
+            out += " - FAILED";
+        }
+        return out;
+    }
+
+    public void setItem(ScriptField_ListAllocs_s.Item item) {
+        mItem = item;
+    }
+
+    public void run() {
+        /* This method needs to be implemented for each subclass */
+        if (mRSTC != null) {
+            mRSTC.refreshTestResults();
+        }
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs
new file mode 100644
index 0000000..3116e5a
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs
@@ -0,0 +1,94 @@
+#include "shared.rsh"
+
+int *a;
+int dimX;
+int dimY;
+int dimZ;
+
+rs_allocation aFaces;
+rs_allocation aLOD;
+rs_allocation aFacesLOD;
+
+static bool test_alloc_dims() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            a[i + j * dimX] = i + j * dimX;
+        }
+    }
+
+    rs_allocation alloc = rsGetAllocation(a);
+    _RS_ASSERT(rsAllocationGetDimX(alloc) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(alloc) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(alloc) == dimZ);
+
+    // Test 2D addressing
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            rsDebug("Verifying ", i + j * dimX);
+            const void *p = rsGetElementAt(alloc, i, j);
+            int val = *(const int *)p;
+            _RS_ASSERT(val == (i + j * dimX));
+        }
+    }
+
+    // Test 1D addressing
+    for (i = 0; i < dimX * dimY; i++) {
+        rsDebug("Verifying ", i);
+        const void *p = rsGetElementAt(alloc, i);
+        int val = *(const int *)p;
+        _RS_ASSERT(val == i);
+    }
+
+    // Test 3D addressing
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            rsDebug("Verifying ", i + j * dimX);
+            const void *p = rsGetElementAt(alloc, i, j, 0);
+            int val = *(const int *)p;
+            _RS_ASSERT(val == (i + j * dimX));
+        }
+    }
+
+    _RS_ASSERT(rsAllocationGetDimX(aFaces) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aFaces) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aFaces) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aFaces) != 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aFaces) == 0);
+
+    _RS_ASSERT(rsAllocationGetDimX(aLOD) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aLOD) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aLOD) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aLOD) == 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aLOD) != 0);
+
+    _RS_ASSERT(rsAllocationGetDimX(aFacesLOD) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aFacesLOD) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aFacesLOD) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aFacesLOD) != 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aFacesLOD) != 0);
+
+    if (failed) {
+        rsDebug("test_alloc_dims FAILED", 0);
+    }
+    else {
+        rsDebug("test_alloc_dims PASSED", 0);
+    }
+
+    return failed;
+}
+
+void alloc_test() {
+    bool failed = false;
+    failed |= test_alloc_dims();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/array_alloc.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/array_alloc.rs
new file mode 100644
index 0000000..74ffdb1
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/array_alloc.rs
@@ -0,0 +1,21 @@
+#include "shared.rsh"
+
+const int dimX = 20;
+rs_allocation a[dimX];
+
+void array_alloc_test() {
+    bool failed = false;
+
+    for (int i = 0; i < dimX; i++) {
+        rsDebug("i: ", i);
+        _RS_ASSERT(rsAllocationGetDimX(a[i]) == 1);
+    }
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/array_init.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/array_init.rs
new file mode 100644
index 0000000..842249a
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/array_init.rs
@@ -0,0 +1,58 @@
+#include "shared.rsh"
+
+// Testing constant array initialization
+float fa[4] = {1.0, 9.9999f};
+double da[2] = {7.0, 8.88888};
+char ca[4] = {'a', 7, 'b', 'c'};
+short sa[4] = {1, 1, 2, 3};
+int ia[4] = {5, 8};
+long la[2] = {13, 21};
+long long lla[4] = {34};
+bool ba[3] = {true, false};
+
+void array_init_test() {
+    bool failed = false;
+
+    _RS_ASSERT(fa[0] == 1.0);
+    _RS_ASSERT(fa[1] == 9.9999f);
+    _RS_ASSERT(fa[2] == 0);
+    _RS_ASSERT(fa[3] == 0);
+
+    _RS_ASSERT(da[0] == 7.0);
+    _RS_ASSERT(da[1] == 8.88888);
+
+    _RS_ASSERT(ca[0] == 'a');
+    _RS_ASSERT(ca[1] == 7);
+    _RS_ASSERT(ca[2] == 'b');
+    _RS_ASSERT(ca[3] == 'c');
+
+    _RS_ASSERT(sa[0] == 1);
+    _RS_ASSERT(sa[1] == 1);
+    _RS_ASSERT(sa[2] == 2);
+    _RS_ASSERT(sa[3] == 3);
+
+    _RS_ASSERT(ia[0] == 5);
+    _RS_ASSERT(ia[1] == 8);
+    _RS_ASSERT(ia[2] == 0);
+    _RS_ASSERT(ia[3] == 0);
+
+    _RS_ASSERT(la[0] == 13);
+    _RS_ASSERT(la[1] == 21);
+
+    _RS_ASSERT(lla[0] == 34);
+    _RS_ASSERT(lla[1] == 0);
+    _RS_ASSERT(lla[2] == 0);
+    _RS_ASSERT(lla[3] == 0);
+
+    _RS_ASSERT(ba[0] == true);
+    _RS_ASSERT(ba[1] == false);
+    _RS_ASSERT(ba[2] == false);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/atomic.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/atomic.rs
new file mode 100644
index 0000000..f0a5041
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/atomic.rs
@@ -0,0 +1,77 @@
+#include "shared.rsh"
+
+// Testing atomic operations
+static bool testUMax(uint32_t dst, uint32_t src) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst > src ? dst : src);
+    uint32_t ret = rsAtomicMax(&dst, src);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool testUMin(uint32_t dst, uint32_t src) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst < src ? dst : src);
+    uint32_t ret = rsAtomicMin(&dst, src);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool testUCas(uint32_t dst, uint32_t cmp, uint32_t swp) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst == cmp ? swp : dst);
+    uint32_t ret = rsAtomicCas(&dst, cmp, swp);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool test_atomics() {
+    bool failed = false;
+
+    failed |= testUMax(5, 6);
+    failed |= testUMax(6, 5);
+    failed |= testUMax(5, 0xf0000006);
+    failed |= testUMax(0xf0000006, 5);
+
+    failed |= testUMin(5, 6);
+    failed |= testUMin(6, 5);
+    failed |= testUMin(5, 0xf0000006);
+    failed |= testUMin(0xf0000006, 5);
+
+    failed |= testUCas(4, 4, 5);
+    failed |= testUCas(4, 5, 5);
+    failed |= testUCas(5, 5, 4);
+    failed |= testUCas(5, 4, 4);
+    failed |= testUCas(0xf0000004, 0xf0000004, 0xf0000005);
+    failed |= testUCas(0xf0000004, 0xf0000005, 0xf0000005);
+    failed |= testUCas(0xf0000005, 0xf0000005, 0xf0000004);
+    failed |= testUCas(0xf0000005, 0xf0000004, 0xf0000004);
+
+    if (failed) {
+        rsDebug("test_atomics FAILED", 0);
+    }
+    else {
+        rsDebug("test_atomics PASSED", 0);
+    }
+
+    return failed;
+}
+
+void atomic_test() {
+    bool failed = false;
+    failed |= test_atomics();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/bug_char.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/bug_char.rs
new file mode 100644
index 0000000..dcd7b72
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/bug_char.rs
@@ -0,0 +1,47 @@
+#include "shared.rsh"
+
+char rand_sc1_0, rand_sc1_1;
+char2 rand_sc2_0, rand_sc2_1;
+
+char min_rand_sc1_sc1;
+char2 min_rand_sc2_sc2;
+
+static bool test_bug_char() {
+    bool failed = false;
+
+    rsDebug("rand_sc2_0.x: ", rand_sc2_0.x);
+    rsDebug("rand_sc2_0.y: ", rand_sc2_0.y);
+    rsDebug("rand_sc2_1.x: ", rand_sc2_1.x);
+    rsDebug("rand_sc2_1.y: ", rand_sc2_1.y);
+    char temp_sc1;
+    char2 temp_sc2;
+
+    temp_sc1 = min( rand_sc1_0, rand_sc1_1 );
+    if (temp_sc1 != min_rand_sc1_sc1) {
+        rsDebug("temp_sc1", temp_sc1);
+        failed = true;
+    }
+    rsDebug("broken", 'y');
+
+    temp_sc2 = min( rand_sc2_0, rand_sc2_1 );
+    if (temp_sc2.x != min_rand_sc2_sc2.x
+            || temp_sc2.y != min_rand_sc2_sc2.y) {
+        failed = true;
+    }
+
+
+    return failed;
+}
+
+void bug_char_test() {
+    bool failed = false;
+    failed |= test_bug_char();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/clamp.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/clamp.rs
new file mode 100644
index 0000000..28b00bd
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/clamp.rs
@@ -0,0 +1,56 @@
+#include "shared.rsh"
+
+static bool test_clamp_vector() {
+    bool failed = false;
+
+    float2 src2 = { 2.0f, 2.0f};
+    float2 min2 = { 0.5f, -3.0f};
+    float2 max2 = { 1.0f, 9.0f};
+
+    float2 res2 = clamp(src2, min2, max2);
+    _RS_ASSERT(res2.x == 1.0f);
+    _RS_ASSERT(res2.y == 2.0f);
+
+
+    float3 src3 = { 2.0f, 2.0f, 1.0f};
+    float3 min3 = { 0.5f, -3.0f, 3.0f};
+    float3 max3 = { 1.0f, 9.0f, 4.0f};
+
+    float3 res3 = clamp(src3, min3, max3);
+    _RS_ASSERT(res3.x == 1.0f);
+    _RS_ASSERT(res3.y == 2.0f);
+    _RS_ASSERT(res3.z == 3.0f);
+
+
+    float4 src4 = { 2.0f, 2.0f, 1.0f, 4.0f };
+    float4 min4 = { 0.5f, -3.0f, 3.0f, 4.0f };
+    float4 max4 = { 1.0f, 9.0f, 4.0f, 4.0f };
+
+    float4 res4 = clamp(src4, min4, max4);
+    _RS_ASSERT(res4.x == 1.0f);
+    _RS_ASSERT(res4.y == 2.0f);
+    _RS_ASSERT(res4.z == 3.0f);
+    _RS_ASSERT(res4.w == 4.0f);
+
+    if (failed) {
+        rsDebug("test_clamp_vector FAILED", 0);
+    }
+    else {
+        rsDebug("test_clamp_vector PASSED", 0);
+    }
+
+    return failed;
+}
+
+void clamp_test() {
+    bool failed = false;
+    failed |= test_clamp_vector();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/clamp_relaxed.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/clamp_relaxed.rs
new file mode 100644
index 0000000..71c65ae
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/clamp_relaxed.rs
@@ -0,0 +1,2 @@
+#include "clamp.rs"
+#pragma rs_fp_relaxed
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/constant.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/constant.rs
new file mode 100644
index 0000000..732eaef
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/constant.rs
@@ -0,0 +1,19 @@
+#include "shared.rsh"
+
+const float floatTest = 1.99f;
+const double doubleTest = 2.05;
+const char charTest = -8;
+const short shortTest = -16;
+const int intTest = -32;
+const long longTest = 17179869184l; // 1 << 34
+const long long longlongTest = 68719476736l; // 1 << 36
+
+const uchar ucharTest = 8;
+const ushort ushortTest = 16;
+const uint uintTest = 32;
+const ulong ulongTest = 4611686018427387904L;
+const int64_t int64_tTest = -17179869184l; // - 1 << 34
+const uint64_t uint64_tTest = 117179869184l;
+
+const bool boolTest = true;
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/convert.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/convert.rs
new file mode 100644
index 0000000..e314f2b
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/convert.rs
@@ -0,0 +1,37 @@
+#include "shared.rsh"
+
+float4 f4 = { 2.0f, 4.0f, 6.0f, 8.0f };
+
+char4 i8_4 = { -1, -2, -3, 4 };
+
+static bool test_convert() {
+    bool failed = false;
+
+    f4 = convert_float4(i8_4);
+    _RS_ASSERT(f4.x == -1.0f);
+    _RS_ASSERT(f4.y == -2.0f);
+    _RS_ASSERT(f4.z == -3.0f);
+    _RS_ASSERT(f4.w == 4.0f);
+
+    if (failed) {
+        rsDebug("test_convert FAILED", 0);
+    }
+    else {
+        rsDebug("test_convert PASSED", 0);
+    }
+
+    return failed;
+}
+
+void convert_test() {
+    bool failed = false;
+    failed |= test_convert();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/convert_relaxed.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/convert_relaxed.rs
new file mode 100644
index 0000000..81abb9b
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/convert_relaxed.rs
@@ -0,0 +1,2 @@
+#include "convert.rs"
+#pragma rs_fp_relaxed
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/copy_test.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/copy_test.rs
new file mode 100644
index 0000000..f4243eb
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/copy_test.rs
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "shared.rsh"
+
+void sendResult(bool pass) {
+    if (pass) {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+}
+
+
+float2 __attribute((kernel)) copyFloat2(float2 i) {
+    return i;
+}
+
+float3 __attribute((kernel)) copyFloat3(float3 i) {
+    return i;
+}
+
+float4 __attribute((kernel)) copyFloat4(float4 i) {
+    return i;
+}
+
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/element.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/element.rs
new file mode 100644
index 0000000..1f24775
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/element.rs
@@ -0,0 +1,156 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_element simpleElem;
+rs_element complexElem;
+typedef struct ComplexStruct {
+    float subElem0;
+    float subElem1;
+    int subElem2;
+    float arrayElem0[2];
+    int arrayElem1[5];
+    char subElem3;
+    float subElem4;
+    float2 subElem5;
+    float3 subElem6;
+    float4 subElem_7;
+} ComplexStruct_t;
+
+ComplexStruct_t *complexStruct;
+
+static const char *subElemNames[] = {
+    "subElem0",
+    "subElem1",
+    "subElem2",
+    "arrayElem0",
+    "arrayElem1",
+    "subElem3",
+    "subElem4",
+    "subElem5",
+    "subElem6",
+    "subElem_7",
+};
+
+static uint32_t subElemNamesSizes[] = {
+    8,
+    8,
+    8,
+    10,
+    10,
+    8,
+    8,
+    8,
+    8,
+    9,
+};
+
+static uint32_t subElemArraySizes[] = {
+    1,
+    1,
+    1,
+    2,
+    5,
+    1,
+    1,
+    1,
+    1,
+    1,
+};
+
+static void resetStruct() {
+    uint8_t *bytePtr = (uint8_t*)complexStruct;
+    uint32_t sizeOfStruct = sizeof(*complexStruct);
+    for(uint32_t i = 0; i < sizeOfStruct; i ++) {
+        bytePtr[i] = 0;
+    }
+}
+
+static bool equals(const char *name0, const char * name1, uint32_t len) {
+    for (uint32_t i = 0; i < len; i ++) {
+        if (name0[i] != name1[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+static bool test_element_getters() {
+    bool failed = false;
+
+    uint32_t subElemOffsets[10];
+    uint32_t index = 0;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem0   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem1   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem2   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->arrayElem0 - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->arrayElem1 - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem3   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem4   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem5   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem6   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem_7  - (uint32_t)complexStruct;
+
+    uint32_t subElemCount = rsElementGetSubElementCount(simpleElem);
+    _RS_ASSERT(subElemCount == 0);
+    _RS_ASSERT(rsElementGetDataType(simpleElem) == RS_TYPE_FLOAT_32);
+    _RS_ASSERT(rsElementGetVectorSize(simpleElem) == 3);
+
+    subElemCount = rsElementGetSubElementCount(complexElem);
+    _RS_ASSERT(subElemCount == 10);
+    _RS_ASSERT(rsElementGetDataType(complexElem) == RS_TYPE_NONE);
+    _RS_ASSERT(rsElementGetVectorSize(complexElem) == 1);
+    _RS_ASSERT(rsElementGetBytesSize(complexElem) == sizeof(*complexStruct));
+
+    char buffer[64];
+    for (uint32_t i = 0; i < subElemCount; i ++) {
+        rs_element subElem = rsElementGetSubElement(complexElem, i);
+        _RS_ASSERT(rsIsObject(subElem));
+
+        _RS_ASSERT(rsElementGetSubElementNameLength(complexElem, i) == subElemNamesSizes[i] + 1);
+
+        uint32_t written = rsElementGetSubElementName(complexElem, i, buffer, 64);
+        _RS_ASSERT(written == subElemNamesSizes[i]);
+        _RS_ASSERT(equals(buffer, subElemNames[i], written));
+
+        _RS_ASSERT(rsElementGetSubElementArraySize(complexElem, i) == subElemArraySizes[i]);
+        _RS_ASSERT(rsElementGetSubElementOffsetBytes(complexElem, i) == subElemOffsets[i]);
+    }
+
+    // Tests error checking
+    rs_element subElem = rsElementGetSubElement(complexElem, subElemCount);
+    _RS_ASSERT(!rsIsObject(subElem));
+
+    _RS_ASSERT(rsElementGetSubElementNameLength(complexElem, subElemCount) == 0);
+
+    _RS_ASSERT(rsElementGetSubElementName(complexElem, subElemCount, buffer, 64) == 0);
+    _RS_ASSERT(rsElementGetSubElementName(complexElem, 0, NULL, 64) == 0);
+    _RS_ASSERT(rsElementGetSubElementName(complexElem, 0, buffer, 0) == 0);
+    uint32_t written = rsElementGetSubElementName(complexElem, 0, buffer, 5);
+    _RS_ASSERT(written == 4);
+    _RS_ASSERT(buffer[4] == '\0');
+
+    _RS_ASSERT(rsElementGetSubElementArraySize(complexElem, subElemCount) == 0);
+    _RS_ASSERT(rsElementGetSubElementOffsetBytes(complexElem, subElemCount) == 0);
+
+    if (failed) {
+        rsDebug("test_element_getters FAILED", 0);
+    }
+    else {
+        rsDebug("test_element_getters PASSED", 0);
+    }
+
+    return failed;
+}
+
+void element_test() {
+    bool failed = false;
+    failed |= test_element_getters();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs
new file mode 100644
index 0000000..ac527b5
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs
@@ -0,0 +1,74 @@
+#include "shared.rsh"
+
+int *a;
+int dimX;
+int dimY;
+static bool failed = false;
+
+void root(int *out, uint32_t x, uint32_t y) {
+    *out = x + y * dimX;
+}
+
+void foo(const int *in, int *out, uint32_t x, uint32_t y) {
+    _RS_ASSERT(*in == (x + y * dimX));
+    *out = 99 + x + y * dimX;
+    _RS_ASSERT(*out == (99 + x + y * dimX));
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            _RS_ASSERT(a[i + j * dimX] == (i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+static bool test_foo_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            _RS_ASSERT(a[i + j * dimX] == (99 + i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_foo_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_foo_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void verify_foo() {
+    failed |= test_foo_output();
+}
+
+void foreach_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs
new file mode 100644
index 0000000..ddf17f8
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs
@@ -0,0 +1,71 @@
+#include "shared.rsh"
+
+int *a;
+int dimX;
+int dimY;
+int xStart = 0;
+int xEnd = 0;
+int yStart = 0;
+int yEnd = 0;
+
+rs_script s;
+rs_allocation ain;
+rs_allocation aout;
+
+void root(int *out, uint32_t x, uint32_t y) {
+    *out = x + y * dimX;
+}
+
+int __attribute__((kernel)) zero() {
+    return 0;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            rsDebug("i: ", i);
+            rsDebug("j: ", j);
+            rsDebug("a[j][i]: ", a[i + j * dimX]);
+            if (i < xStart || i >= xEnd || j < yStart || j >= yEnd) {
+                _RS_ASSERT(a[i + j * dimX] == 0);
+            } else {
+                _RS_ASSERT(a[i + j * dimX] == (i + j * dimX));
+            }
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void foreach_bounds_test() {
+    static bool failed = false;
+
+    rs_script_call_t rssc = {0};
+    rssc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
+    rssc.xStart = xStart;
+    rssc.xEnd = xEnd;
+    rssc.yStart = yStart;
+    rssc.yEnd = yEnd;
+
+    rsForEach(s, ain, aout, NULL, 0, &rssc);
+
+    failed |= test_root_output();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/fp_mad.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/fp_mad.rs
new file mode 100644
index 0000000..b6f2b2a6
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/fp_mad.rs
@@ -0,0 +1,174 @@
+#include "shared.rsh"
+
+const int TEST_COUNT = 1;
+
+static float data_f1[1025];
+static float4 data_f4[1025];
+
+static void test_mad4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~1 billion ops
+    for (int ct=0; ct < 1000 * (1000 / 80); ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = (data_f4[i] * 0.02f +
+                          data_f4[i+1] * 0.04f +
+                          data_f4[i+2] * 0.05f +
+                          data_f4[i+3] * 0.1f +
+                          data_f4[i+4] * 0.2f +
+                          data_f4[i+5] * 0.2f +
+                          data_f4[i+6] * 0.1f +
+                          data_f4[i+7] * 0.05f +
+                          data_f4[i+8] * 0.04f +
+                          data_f4[i+9] * 0.02f + 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_mad4 M ops", 1000.f / time);
+}
+
+static void test_mad(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~1 billion ops
+    for (int ct=0; ct < 1000 * (1000 / 20); ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = (data_f1[i] * 0.02f +
+                          data_f1[i+1] * 0.04f +
+                          data_f1[i+2] * 0.05f +
+                          data_f1[i+3] * 0.1f +
+                          data_f1[i+4] * 0.2f +
+                          data_f1[i+5] * 0.2f +
+                          data_f1[i+6] * 0.1f +
+                          data_f1[i+7] * 0.05f +
+                          data_f1[i+8] * 0.04f +
+                          data_f1[i+9] * 0.02f + 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_mad M ops", 1000.f / time);
+}
+
+static void test_norm(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = normalize(data_f4[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_norm M ops", 10.f / time);
+}
+
+static void test_sincos4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10 / 4; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = sin(data_f4[i]) * cos(data_f4[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_sincos4 M ops", 10.f / time);
+}
+
+static void test_sincos(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = sin(data_f1[i]) * cos(data_f1[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_sincos M ops", 10.f / time);
+}
+
+static void test_clamp(uint32_t index) {
+    start();
+
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = clamp(data_f1[i], -1.f, 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_clamp M ops", 100.f / time);
+
+    start();
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100; ct++) {
+        for (int i=0; i < (1000); i++) {
+            if (data_f1[i] < -1.f) data_f1[i] = -1.f;
+            if (data_f1[i] > -1.f) data_f1[i] = 1.f;
+        }
+    }
+
+    time = end(index);
+    rsDebug("fp_clamp ref M ops", 100.f / time);
+}
+
+static void test_clamp4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100 /4; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = clamp(data_f4[i], -1.f, 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_clamp4 M ops", 100.f / time);
+}
+
+void fp_mad_test(uint32_t index, int test_num) {
+    int x;
+    for (x=0; x < 1025; x++) {
+        data_f1[x] = (x & 0xf) * 0.1f;
+        data_f4[x].x = (x & 0xf) * 0.1f;
+        data_f4[x].y = (x & 0xf0) * 0.1f;
+        data_f4[x].z = (x & 0x33) * 0.1f;
+        data_f4[x].w = (x & 0x77) * 0.1f;
+    }
+
+    test_mad4(index);
+    test_mad(index);
+
+    for (x=0; x < 1025; x++) {
+        data_f1[x] = (x & 0xf) * 0.1f + 1.f;
+        data_f4[x].x = (x & 0xf) * 0.1f + 1.f;
+        data_f4[x].y = (x & 0xf0) * 0.1f + 1.f;
+        data_f4[x].z = (x & 0x33) * 0.1f + 1.f;
+        data_f4[x].w = (x & 0x77) * 0.1f + 1.f;
+    }
+
+    test_norm(index);
+    test_sincos4(index);
+    test_sincos(index);
+    test_clamp4(index);
+    test_clamp(index);
+
+    // TODO Actually verify test result accuracy
+    rsDebug("fp_mad_test PASSED", 0);
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+}
+
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/int4.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/int4.rs
new file mode 100644
index 0000000..c791cab
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/int4.rs
@@ -0,0 +1,29 @@
+#include "shared.rsh"
+#pragma rs_fp_relaxed
+
+uchar4 u4 = 4;
+int4 gi4 = {2, 2, 2, 2};
+
+void int4_test() {
+    bool failed = false;
+    int4 i4 = {u4.x, u4.y, u4.z, u4.w};
+    i4 *= gi4;
+
+    rsDebug("i4.x", i4.x);
+    rsDebug("i4.y", i4.y);
+    rsDebug("i4.z", i4.z);
+    rsDebug("i4.w", i4.w);
+
+    _RS_ASSERT(i4.x == 8);
+    _RS_ASSERT(i4.y == 8);
+    _RS_ASSERT(i4.z == 8);
+    _RS_ASSERT(i4.w == 8);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/kernel.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/kernel.rs
new file mode 100644
index 0000000..d6c9df3
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/kernel.rs
@@ -0,0 +1,47 @@
+#include "shared.rsh"
+
+int *ain;
+int *aout;
+int dimX;
+static bool failed = false;
+
+void init_vars(int *out) {
+    *out = 7;
+}
+
+
+int __attribute__((kernel)) root(int ain, uint32_t x) {
+    _RS_ASSERT(ain == 7);
+    return ain + x;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i;
+
+    for (i = 0; i < dimX; i++) {
+        _RS_ASSERT(aout[i] == (i + ain[i]));
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void kernel_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/kernel_struct.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/kernel_struct.rs
new file mode 100644
index 0000000..62c30ae
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/kernel_struct.rs
@@ -0,0 +1,66 @@
+#include "shared.rsh"
+
+struct simpleStruct {
+    int i1;
+    char ignored1;
+    float f1;
+    int i2;
+    char ignored2;
+    float f2;
+};
+
+struct simpleStruct *ain;
+struct simpleStruct *aout;
+int dimX;
+static bool failed = false;
+
+void init_vars(struct simpleStruct *out, uint32_t x) {
+    out->i1 = 0;
+    out->f1 = 0.f;
+    out->i2 = 1;
+    out->f2 = 1.0f;
+}
+
+struct simpleStruct __attribute__((kernel))
+        root(struct simpleStruct in, uint32_t x) {
+    struct simpleStruct s;
+    s.i1 = in.i1 + x;
+    s.f1 = in.f1 + x;
+    s.i2 = in.i2 + x;
+    s.f2 = in.f2 + x;
+    return s;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i;
+
+    for (i = 0; i < dimX; i++) {
+        _RS_ASSERT(aout[i].i1 == (i + ain[i].i1));
+        _RS_ASSERT(aout[i].f1 == (i + ain[i].f1));
+        _RS_ASSERT(aout[i].i2 == (i + ain[i].i2));
+        _RS_ASSERT(aout[i].f2 == (i + ain[i].f2));
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void kernel_struct_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math.rs
new file mode 100644
index 0000000..aae29a4
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math.rs
@@ -0,0 +1,436 @@
+#include "shared.rsh"
+
+// Testing math library
+
+volatile float f1;
+volatile float2 f2;
+volatile float3 f3;
+volatile float4 f4;
+
+volatile int i1;
+volatile int2 i2;
+volatile int3 i3;
+volatile int4 i4;
+
+volatile uint ui1;
+volatile uint2 ui2;
+volatile uint3 ui3;
+volatile uint4 ui4;
+
+volatile short s1;
+volatile short2 s2;
+volatile short3 s3;
+volatile short4 s4;
+
+volatile ushort us1;
+volatile ushort2 us2;
+volatile ushort3 us3;
+volatile ushort4 us4;
+
+volatile char c1;
+volatile char2 c2;
+volatile char3 c3;
+volatile char4 c4;
+
+volatile uchar uc1;
+volatile uchar2 uc2;
+volatile uchar3 uc3;
+volatile uchar4 uc4;
+
+#define DECL_INT(prefix)            \
+volatile char prefix##_c_1 = 1;     \
+volatile char2 prefix##_c_2 = 1;    \
+volatile char3 prefix##_c_3 = 1;    \
+volatile char4 prefix##_c_4 = 1;    \
+volatile uchar prefix##_uc_1 = 1;   \
+volatile uchar2 prefix##_uc_2 = 1;  \
+volatile uchar3 prefix##_uc_3 = 1;  \
+volatile uchar4 prefix##_uc_4 = 1;  \
+volatile short prefix##_s_1 = 1;    \
+volatile short2 prefix##_s_2 = 1;   \
+volatile short3 prefix##_s_3 = 1;   \
+volatile short4 prefix##_s_4 = 1;   \
+volatile ushort prefix##_us_1 = 1;  \
+volatile ushort2 prefix##_us_2 = 1; \
+volatile ushort3 prefix##_us_3 = 1; \
+volatile ushort4 prefix##_us_4 = 1; \
+volatile int prefix##_i_1 = 1;      \
+volatile int2 prefix##_i_2 = 1;     \
+volatile int3 prefix##_i_3 = 1;     \
+volatile int4 prefix##_i_4 = 1;     \
+volatile uint prefix##_ui_1 = 1;    \
+volatile uint2 prefix##_ui_2 = 1;   \
+volatile uint3 prefix##_ui_3 = 1;   \
+volatile uint4 prefix##_ui_4 = 1;   \
+volatile long prefix##_l_1 = 1;     \
+volatile ulong prefix##_ul_1 = 1;
+
+DECL_INT(res)
+DECL_INT(src1)
+DECL_INT(src2)
+
+#define TEST_INT_OP_TYPE(op, type)                      \
+rsDebug("Testing " #op " for " #type "1", i++);         \
+res_##type##_1 = src1_##type##_1 op src2_##type##_1;    \
+rsDebug("Testing " #op " for " #type "2", i++);         \
+res_##type##_2 = src1_##type##_2 op src2_##type##_2;    \
+rsDebug("Testing " #op " for " #type "3", i++);         \
+res_##type##_3 = src1_##type##_3 op src2_##type##_3;    \
+rsDebug("Testing " #op " for " #type "4", i++);         \
+res_##type##_4 = src1_##type##_4 op src2_##type##_4;
+
+#define TEST_INT_OP(op)                     \
+TEST_INT_OP_TYPE(op, c)                     \
+TEST_INT_OP_TYPE(op, uc)                    \
+TEST_INT_OP_TYPE(op, s)                     \
+TEST_INT_OP_TYPE(op, us)                    \
+TEST_INT_OP_TYPE(op, i)                     \
+TEST_INT_OP_TYPE(op, ui)                    \
+rsDebug("Testing " #op " for l1", i++);     \
+res_l_1 = src1_l_1 op src2_l_1;             \
+rsDebug("Testing " #op " for ul1", i++);    \
+res_ul_1 = src1_ul_1 op src2_ul_1;
+
+#define TEST_XN_FUNC_YN(typeout, fnc, typein)   \
+    res_##typeout##_1 = fnc(src1_##typein##_1); \
+    res_##typeout##_2 = fnc(src1_##typein##_2); \
+    res_##typeout##_3 = fnc(src1_##typein##_3); \
+    res_##typeout##_4 = fnc(src1_##typein##_4);
+
+#define TEST_XN_FUNC_XN_XN(type, fnc)                       \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1); \
+    res_##type##_2 = fnc(src1_##type##_2, src2_##type##_2); \
+    res_##type##_3 = fnc(src1_##type##_3, src2_##type##_3); \
+    res_##type##_4 = fnc(src1_##type##_4, src2_##type##_4);
+
+#define TEST_X_FUNC_X_X_X(type, fnc)    \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1, src2_##type##_1);
+
+#define TEST_IN_FUNC_IN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, uc)    \
+    TEST_XN_FUNC_YN(c, fnc, c)      \
+    TEST_XN_FUNC_YN(us, fnc, us)    \
+    TEST_XN_FUNC_YN(s, fnc, s)      \
+    TEST_XN_FUNC_YN(ui, fnc, ui)    \
+    TEST_XN_FUNC_YN(i, fnc, i)
+
+#define TEST_UIN_FUNC_IN(fnc)       \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, c)     \
+    TEST_XN_FUNC_YN(us, fnc, s)     \
+    TEST_XN_FUNC_YN(ui, fnc, i)     \
+
+#define TEST_IN_FUNC_IN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_XN_XN(uc, fnc)     \
+    TEST_XN_FUNC_XN_XN(c, fnc)      \
+    TEST_XN_FUNC_XN_XN(us, fnc)     \
+    TEST_XN_FUNC_XN_XN(s, fnc)      \
+    TEST_XN_FUNC_XN_XN(ui, fnc)     \
+    TEST_XN_FUNC_XN_XN(i, fnc)
+
+#define TEST_I_FUNC_I_I_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_X_FUNC_X_X_X(uc, fnc)      \
+    TEST_X_FUNC_X_X_X(c, fnc)       \
+    TEST_X_FUNC_X_X_X(us, fnc)      \
+    TEST_X_FUNC_X_X_X(s, fnc)       \
+    TEST_X_FUNC_X_X_X(ui, fnc)      \
+    TEST_X_FUNC_X_X_X(i, fnc)
+
+#define TEST_FN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f2 = fnc(f2);                   \
+    f3 = fnc(f3);                   \
+    f4 = fnc(f4);
+
+#define TEST_FN_FUNC_FN_PFN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (float*) &f1);     \
+    f2 = fnc(f2, (float2*) &f2);    \
+    f3 = fnc(f3, (float3*) &f3);    \
+    f4 = fnc(f4, (float4*) &f4);
+
+#define TEST_FN_FUNC_FN_FN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f2);               \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_F34_FUNC_F34_F34(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_F(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f1);               \
+    f3 = fnc(f3, f1);               \
+    f4 = fnc(f4, f1);
+
+#define TEST_F_FUNC_FN(fnc)         \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f1 = fnc(f2);                   \
+    f1 = fnc(f3);                   \
+    f1 = fnc(f4);
+
+#define TEST_F_FUNC_FN_FN(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f1 = fnc(f2, f2);               \
+    f1 = fnc(f3, f3);               \
+    f1 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i2);               \
+    f3 = fnc(f3, i3);               \
+    f4 = fnc(f4, i4);
+
+#define TEST_FN_FUNC_FN_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i1);               \
+    f3 = fnc(f3, i1);               \
+    f4 = fnc(f4, i1);
+
+#define TEST_FN_FUNC_FN_FN_FN(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f2, f2);           \
+    f3 = fnc(f3, f3, f3);           \
+    f4 = fnc(f4, f4, f4);
+
+#define TEST_FN_FUNC_FN_FN_F(fnc)   \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f1, f1);           \
+    f3 = fnc(f3, f1, f1);           \
+    f4 = fnc(f4, f1, f1);
+
+#define TEST_FN_FUNC_FN_PIN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (int*) &i1);       \
+    f2 = fnc(f2, (int2*) &i2);      \
+    f3 = fnc(f3, (int3*) &i3);      \
+    f4 = fnc(f4, (int4*) &i4);
+
+#define TEST_FN_FUNC_FN_FN_PIN(fnc) \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, (int*) &i1);   \
+    f2 = fnc(f2, f2, (int2*) &i2);  \
+    f3 = fnc(f3, f3, (int3*) &i3);  \
+    f4 = fnc(f4, f4, (int4*) &i4);
+
+#define TEST_IN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    i1 = fnc(f1);                   \
+    i2 = fnc(f2);                   \
+    i3 = fnc(f3);                   \
+    i4 = fnc(f4);
+
+static bool test_fp_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_FN_FUNC_FN(acos);
+    TEST_FN_FUNC_FN(acosh);
+    TEST_FN_FUNC_FN(acospi);
+    TEST_FN_FUNC_FN(asin);
+    TEST_FN_FUNC_FN(asinh);
+    TEST_FN_FUNC_FN(asinpi);
+    TEST_FN_FUNC_FN(atan);
+    TEST_FN_FUNC_FN_FN(atan2);
+    TEST_FN_FUNC_FN(atanh);
+    TEST_FN_FUNC_FN(atanpi);
+    TEST_FN_FUNC_FN_FN(atan2pi);
+    TEST_FN_FUNC_FN(cbrt);
+    TEST_FN_FUNC_FN(ceil);
+    TEST_FN_FUNC_FN_FN_FN(clamp);
+    TEST_FN_FUNC_FN_FN_F(clamp);
+    TEST_FN_FUNC_FN_FN(copysign);
+    TEST_FN_FUNC_FN(cos);
+    TEST_FN_FUNC_FN(cosh);
+    TEST_FN_FUNC_FN(cospi);
+    TEST_F34_FUNC_F34_F34(cross);
+    TEST_FN_FUNC_FN(degrees);
+    TEST_F_FUNC_FN_FN(distance);
+    TEST_F_FUNC_FN_FN(dot);
+    TEST_FN_FUNC_FN(erfc);
+    TEST_FN_FUNC_FN(erf);
+    TEST_FN_FUNC_FN(exp);
+    TEST_FN_FUNC_FN(exp2);
+    TEST_FN_FUNC_FN(exp10);
+    TEST_FN_FUNC_FN(expm1);
+    TEST_FN_FUNC_FN(fabs);
+    TEST_FN_FUNC_FN_FN(fdim);
+    TEST_FN_FUNC_FN(floor);
+    TEST_FN_FUNC_FN_FN_FN(fma);
+    TEST_FN_FUNC_FN_FN(fmax);
+    TEST_FN_FUNC_FN_F(fmax);
+    TEST_FN_FUNC_FN_FN(fmin);
+    TEST_FN_FUNC_FN_F(fmin);
+    TEST_FN_FUNC_FN_FN(fmod);
+    TEST_FN_FUNC_FN_PFN(fract);
+    TEST_FN_FUNC_FN_PIN(frexp);
+    TEST_FN_FUNC_FN_FN(hypot);
+    TEST_IN_FUNC_FN(ilogb);
+    TEST_FN_FUNC_FN_IN(ldexp);
+    TEST_FN_FUNC_FN_I(ldexp);
+    TEST_F_FUNC_FN(length);
+    TEST_FN_FUNC_FN(lgamma);
+    TEST_FN_FUNC_FN_PIN(lgamma);
+    TEST_FN_FUNC_FN(log);
+    TEST_FN_FUNC_FN(log2);
+    TEST_FN_FUNC_FN(log10);
+    TEST_FN_FUNC_FN(log1p);
+    TEST_FN_FUNC_FN(logb);
+    TEST_FN_FUNC_FN_FN_FN(mad);
+    TEST_FN_FUNC_FN_FN(max);
+    TEST_FN_FUNC_FN_F(max);
+    TEST_FN_FUNC_FN_FN(min);
+    TEST_FN_FUNC_FN_F(min);
+    TEST_FN_FUNC_FN_FN_FN(mix);
+    TEST_FN_FUNC_FN_FN_F(mix);
+    TEST_FN_FUNC_FN_PFN(modf);
+    // nan
+    TEST_FN_FUNC_FN_FN(nextafter);
+    TEST_FN_FUNC_FN(normalize);
+    TEST_FN_FUNC_FN_FN(pow);
+    TEST_FN_FUNC_FN_IN(pown);
+    TEST_FN_FUNC_FN_FN(powr);
+    TEST_FN_FUNC_FN(radians);
+    TEST_FN_FUNC_FN_FN(remainder);
+    TEST_FN_FUNC_FN_FN_PIN(remquo);
+    TEST_FN_FUNC_FN(rint);
+    TEST_FN_FUNC_FN_IN(rootn);
+    TEST_FN_FUNC_FN(round);
+    TEST_FN_FUNC_FN(rsqrt);
+    TEST_FN_FUNC_FN(sign);
+    TEST_FN_FUNC_FN(sin);
+    TEST_FN_FUNC_FN_PFN(sincos);
+    TEST_FN_FUNC_FN(sinh);
+    TEST_FN_FUNC_FN(sinpi);
+    TEST_FN_FUNC_FN(sqrt);
+    TEST_FN_FUNC_FN_FN(step);
+    TEST_FN_FUNC_FN_F(step);
+    TEST_FN_FUNC_FN(tan);
+    TEST_FN_FUNC_FN(tanh);
+    TEST_FN_FUNC_FN(tanpi);
+    TEST_FN_FUNC_FN(tgamma);
+    TEST_FN_FUNC_FN(trunc);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_fp_math FAILED", time);
+    }
+    else {
+        rsDebug("test_fp_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_int_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_UIN_FUNC_IN(abs);
+    TEST_IN_FUNC_IN(clz);
+    TEST_IN_FUNC_IN_IN(min);
+    TEST_IN_FUNC_IN_IN(max);
+    TEST_I_FUNC_I_I_I(rsClamp);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_int_math FAILED", time);
+    }
+    else {
+        rsDebug("test_int_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_basic_operators() {
+    bool failed = false;
+    int i = 0;
+
+    TEST_INT_OP(+);
+    TEST_INT_OP(-);
+    TEST_INT_OP(*);
+    TEST_INT_OP(/);
+    TEST_INT_OP(%);
+    TEST_INT_OP(<<);
+    TEST_INT_OP(>>);
+
+    if (failed) {
+        rsDebug("test_basic_operators FAILED", 0);
+    }
+    else {
+        rsDebug("test_basic_operators PASSED", 0);
+    }
+
+    return failed;
+}
+
+#define TEST_CVT(to, from, type)                        \
+rsDebug("Testing convert from " #from " to " #to, 0);   \
+to##1 = from##1;                                        \
+to##2 = convert_##type##2(from##2);                     \
+to##3 = convert_##type##3(from##3);                     \
+to##4 = convert_##type##4(from##4);
+
+#define TEST_CVT_MATRIX(to, type)   \
+TEST_CVT(to, c, type);              \
+TEST_CVT(to, uc, type);             \
+TEST_CVT(to, s, type);              \
+TEST_CVT(to, us, type);             \
+TEST_CVT(to, i, type);              \
+TEST_CVT(to, ui, type);             \
+TEST_CVT(to, f, type);              \
+
+static bool test_convert() {
+    bool failed = false;
+
+    TEST_CVT_MATRIX(c, char);
+    TEST_CVT_MATRIX(uc, uchar);
+    TEST_CVT_MATRIX(s, short);
+    TEST_CVT_MATRIX(us, ushort);
+    TEST_CVT_MATRIX(i, int);
+    TEST_CVT_MATRIX(ui, uint);
+    TEST_CVT_MATRIX(f, float);
+
+    if (failed) {
+        rsDebug("test_convert FAILED", 0);
+    }
+    else {
+        rsDebug("test_convert PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_test(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= test_convert();
+    failed |= test_fp_math(index);
+    failed |= test_int_math(index);
+    failed |= test_basic_operators();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math_agree.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math_agree.rs
new file mode 100644
index 0000000..5bfbb2b
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math_agree.rs
@@ -0,0 +1,409 @@
+#include "shared.rsh"
+//#pragma rs_fp_relaxed
+
+volatile float x = 0.0f;
+volatile float y = 0.0f;
+volatile float result_add = 0.0f;
+volatile float result_sub = 0.0f;
+volatile float result_mul = 0.0f;
+volatile float result_div = 0.0f;
+
+#define DECLARE_INPUT_SET(type, abbrev)         \
+volatile type    rand_##abbrev##1_0, rand_##abbrev##1_1; \
+volatile type##2 rand_##abbrev##2_0, rand_##abbrev##2_1; \
+volatile type##3 rand_##abbrev##3_0, rand_##abbrev##3_1; \
+volatile type##4 rand_##abbrev##4_0, rand_##abbrev##4_1;
+
+#define DECLARE_ALL_INPUT_SETS()    \
+DECLARE_INPUT_SET(float, f);        \
+DECLARE_INPUT_SET(char, sc);        \
+DECLARE_INPUT_SET(uchar, uc);       \
+DECLARE_INPUT_SET(short, ss);       \
+DECLARE_INPUT_SET(ushort, us);      \
+DECLARE_INPUT_SET(int, si);         \
+DECLARE_INPUT_SET(uint, ui);        \
+DECLARE_INPUT_SET(long, sl);        \
+DECLARE_INPUT_SET(ulong, ul);
+
+DECLARE_ALL_INPUT_SETS();
+
+#define DECLARE_REFERENCE_SET_VEC_VEC(type, abbrev, func)   \
+volatile type    func##_rand_##abbrev##1_##abbrev##1;                \
+volatile type##2 func##_rand_##abbrev##2_##abbrev##2;                \
+volatile type##3 func##_rand_##abbrev##3_##abbrev##3;                \
+volatile type##4 func##_rand_##abbrev##4_##abbrev##4;
+#define DECLARE_REFERENCE_SET_VEC_SCL(type, abbrev, func)   \
+volatile type##2 func##_rand_##abbrev##2_##abbrev##1;                \
+volatile type##3 func##_rand_##abbrev##3_##abbrev##1;                \
+volatile type##4 func##_rand_##abbrev##4_##abbrev##1;
+
+#define DECLARE_ALL_REFERENCE_SETS_VEC_VEC(func)    \
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(char, sc, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(uchar, uc, func);     \
+DECLARE_REFERENCE_SET_VEC_VEC(short, ss, func);     \
+DECLARE_REFERENCE_SET_VEC_VEC(ushort, us, func);    \
+DECLARE_REFERENCE_SET_VEC_VEC(int, si, func);       \
+DECLARE_REFERENCE_SET_VEC_VEC(uint, ui, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(long, sl, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(ulong, ul, func);
+
+DECLARE_ALL_REFERENCE_SETS_VEC_VEC(min);
+DECLARE_ALL_REFERENCE_SETS_VEC_VEC(max);
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmin);
+DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmin);
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmax);
+DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmax);
+
+static void fail_f1(float v1, float v2, float actual, float expected, char *op_name) {
+    int dist = float_dist(actual, expected);
+    rsDebug("float operation did not match!", op_name);
+    rsDebug("v1", v1);
+    rsDebug("v2", v2);
+    rsDebug("Dalvik result", expected);
+    rsDebug("Renderscript result", actual);
+    rsDebug("ULP difference", dist);
+}
+
+static void fail_f2(float2 v1, float2 v2, float2 actual, float2 expected, char *op_name) {
+    int2 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    rsDebug("float2 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+}
+
+static void fail_f3(float3 v1, float3 v2, float3 actual, float3 expected, char *op_name) {
+    int3 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    dist.z = float_dist(actual.z, expected.z);
+    rsDebug("float3 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v1.z", v1.z);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("v2.z", v2.z);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Dalvik result .z", expected.z);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("Renderscript result .z", actual.z);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+    rsDebug("ULP difference .z", dist.z);
+}
+
+static void fail_f4(float4 v1, float4 v2, float4 actual, float4 expected, char *op_name) {
+    int4 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    dist.z = float_dist(actual.z, expected.z);
+    dist.w = float_dist(actual.w, expected.w);
+    rsDebug("float4 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v1.z", v1.z);
+    rsDebug("v1.w", v1.w);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("v2.z", v2.z);
+    rsDebug("v2.w", v2.w);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Dalvik result .z", expected.z);
+    rsDebug("Dalvik result .w", expected.w);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("Renderscript result .z", actual.z);
+    rsDebug("Renderscript result .w", actual.w);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+    rsDebug("ULP difference .z", dist.z);
+    rsDebug("ULP difference .w", dist.w);
+}
+
+static bool f1_almost_equal(float a, float b) {
+    return float_almost_equal(a, b);
+}
+
+static bool f2_almost_equal(float2 a, float2 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y);
+}
+
+
+static bool f3_almost_equal(float3 a, float3 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y)
+            && float_almost_equal(a.z, b.z);
+}
+
+static bool f4_almost_equal(float4 a, float4 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y)
+            && float_almost_equal(a.z, b.z) && float_almost_equal(a.w, b.w);
+}
+
+#define TEST_BASIC_FLOAT_OP(op, opName)                 \
+temp_f1 = x op y;                                       \
+if (! float_almost_equal(temp_f1, result_##opName)) {   \
+    fail_f1(x, y , temp_f1, result_##opName, #opName);  \
+    failed = true;                                      \
+}
+
+#define TEST_FN_FN(func, size)                                                  \
+temp_f##size = func(rand_f##size##_0, rand_f##size##_1);                        \
+if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f##size)) {   \
+    fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f##size, #func);   \
+    failed = true;                                                              \
+}
+#define TEST_FN_F(func, size)                                               \
+temp_f##size = func(rand_f##size##_0, rand_f1_1);                           \
+if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f1)) {    \
+    fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f1 , #func);   \
+    failed = true;                                                          \
+}
+
+#define TEST_FN_FN_ALL(func)    \
+TEST_FN_FN(func, 1)             \
+TEST_FN_FN(func, 2)             \
+TEST_FN_FN(func, 3)             \
+TEST_FN_FN(func, 4)
+#define TEST_FN_F_ALL(func) \
+TEST_FN_F(func, 2)          \
+TEST_FN_F(func, 3)          \
+TEST_FN_F(func, 4)
+
+#define TEST_VEC1_VEC1(func, type)                              \
+temp_##type##1 = func( rand_##type##1_0, rand_##type##1_1 );    \
+if (temp_##type##1 != func##_rand_##type##1_##type##1) {        \
+    rsDebug(#func " " #type "1 operation did not match!", 0);   \
+    rsDebug("v1", rand_##type##1_0);                            \
+    rsDebug("v2", rand_##type##1_1);                            \
+    rsDebug("Dalvik result", func##_rand_##type##1_##type##1);  \
+    rsDebug("Renderscript result", temp_##type##1);             \
+    failed = true;                                              \
+}
+#define TEST_VEC2_VEC2(func, type)                                      \
+temp_##type##2 = func( rand_##type##2_0, rand_##type##2_1 );            \
+if (temp_##type##2 .x != func##_rand_##type##2_##type##2 .x             \
+        || temp_##type##2 .y != func##_rand_##type##2_##type##2 .y) {   \
+    rsDebug(#func " " #type "2 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##2_0 .x);                               \
+    rsDebug("v1.y", rand_##type##2_0 .y);                               \
+    rsDebug("v2.x", rand_##type##2_1 .x);                               \
+    rsDebug("v2.y", rand_##type##2_1 .y);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##2_##type##2 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##2_##type##2 .y);    \
+    rsDebug("Renderscript result .x", temp_##type##2 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##2 .y);               \
+    failed = true;                                                      \
+}
+#define TEST_VEC3_VEC3(func, type)                                      \
+temp_##type##3 = func( rand_##type##3_0, rand_##type##3_1 );            \
+if (temp_##type##3 .x != func##_rand_##type##3_##type##3 .x             \
+        || temp_##type##3 .y != func##_rand_##type##3_##type##3 .y      \
+        || temp_##type##3 .z != func##_rand_##type##3_##type##3 .z) {   \
+    rsDebug(#func " " #type "3 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##3_0 .x);                               \
+    rsDebug("v1.y", rand_##type##3_0 .y);                               \
+    rsDebug("v1.z", rand_##type##3_0 .z);                               \
+    rsDebug("v2.x", rand_##type##3_1 .x);                               \
+    rsDebug("v2.y", rand_##type##3_1 .y);                               \
+    rsDebug("v2.z", rand_##type##3_1 .z);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##3_##type##3 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##3_##type##3 .y);    \
+    rsDebug("Dalvik result .z", func##_rand_##type##3_##type##3 .z);    \
+    rsDebug("Renderscript result .x", temp_##type##3 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##3 .y);               \
+    rsDebug("Renderscript result .z", temp_##type##3 .z);               \
+    failed = true;                                                      \
+}
+#define TEST_VEC4_VEC4(func, type)                                      \
+temp_##type##4 = func( rand_##type##4_0, rand_##type##4_1 );            \
+if (temp_##type##4 .x != func##_rand_##type##4_##type##4 .x             \
+        || temp_##type##4 .y != func##_rand_##type##4_##type##4 .y      \
+        || temp_##type##4 .z != func##_rand_##type##4_##type##4 .z      \
+        || temp_##type##4 .w != func##_rand_##type##4_##type##4 .w) {   \
+    rsDebug(#func " " #type "4 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##4_0 .x);                               \
+    rsDebug("v1.y", rand_##type##4_0 .y);                               \
+    rsDebug("v1.z", rand_##type##4_0 .z);                               \
+    rsDebug("v1.w", rand_##type##4_0 .w);                               \
+    rsDebug("v2.x", rand_##type##4_1 .x);                               \
+    rsDebug("v2.y", rand_##type##4_1 .y);                               \
+    rsDebug("v2.z", rand_##type##4_1 .z);                               \
+    rsDebug("v2.w", rand_##type##4_1 .w);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##4_##type##4 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##4_##type##4 .y);    \
+    rsDebug("Dalvik result .z", func##_rand_##type##4_##type##4 .z);    \
+    rsDebug("Dalvik result .w", func##_rand_##type##4_##type##4 .w);    \
+    rsDebug("Renderscript result .x", temp_##type##4 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##4 .y);               \
+    rsDebug("Renderscript result .z", temp_##type##4 .z);               \
+    rsDebug("Renderscript result .w", temp_##type##4 .w);               \
+    failed = true;                                                      \
+}
+
+#define TEST_SC1_SC1(func)  TEST_VEC1_VEC1(func, sc)
+#define TEST_SC2_SC2(func)  TEST_VEC2_VEC2(func, sc)
+#define TEST_SC3_SC3(func)  TEST_VEC3_VEC3(func, sc)
+#define TEST_SC4_SC4(func)  TEST_VEC4_VEC4(func, sc)
+
+#define TEST_UC1_UC1(func)  TEST_VEC1_VEC1(func, uc)
+#define TEST_UC2_UC2(func)  TEST_VEC2_VEC2(func, uc)
+#define TEST_UC3_UC3(func)  TEST_VEC3_VEC3(func, uc)
+#define TEST_UC4_UC4(func)  TEST_VEC4_VEC4(func, uc)
+
+#define TEST_SS1_SS1(func)  TEST_VEC1_VEC1(func, ss)
+#define TEST_SS2_SS2(func)  TEST_VEC2_VEC2(func, ss)
+#define TEST_SS3_SS3(func)  TEST_VEC3_VEC3(func, ss)
+#define TEST_SS4_SS4(func)  TEST_VEC4_VEC4(func, ss)
+
+#define TEST_US1_US1(func)  TEST_VEC1_VEC1(func, us)
+#define TEST_US2_US2(func)  TEST_VEC2_VEC2(func, us)
+#define TEST_US3_US3(func)  TEST_VEC3_VEC3(func, us)
+#define TEST_US4_US4(func)  TEST_VEC4_VEC4(func, us)
+
+#define TEST_SI1_SI1(func)  TEST_VEC1_VEC1(func, si)
+#define TEST_SI2_SI2(func)  TEST_VEC2_VEC2(func, si)
+#define TEST_SI3_SI3(func)  TEST_VEC3_VEC3(func, si)
+#define TEST_SI4_SI4(func)  TEST_VEC4_VEC4(func, si)
+
+#define TEST_UI1_UI1(func)  TEST_VEC1_VEC1(func, ui)
+#define TEST_UI2_UI2(func)  TEST_VEC2_VEC2(func, ui)
+#define TEST_UI3_UI3(func)  TEST_VEC3_VEC3(func, ui)
+#define TEST_UI4_UI4(func)  TEST_VEC4_VEC4(func, ui)
+
+#define TEST_SL1_SL1(func)  TEST_VEC1_VEC1(func, sl)
+#define TEST_SL2_SL2(func)  TEST_VEC2_VEC2(func, sl)
+#define TEST_SL3_SL3(func)  TEST_VEC3_VEC3(func, sl)
+#define TEST_SL4_SL4(func)  TEST_VEC4_VEC4(func, sl)
+
+#define TEST_UL1_UL1(func)  TEST_VEC1_VEC1(func, ul)
+#define TEST_UL2_UL2(func)  TEST_VEC2_VEC2(func, ul)
+#define TEST_UL3_UL3(func)  TEST_VEC3_VEC3(func, ul)
+#define TEST_UL4_UL4(func)  TEST_VEC4_VEC4(func, ul)
+
+#define TEST_SC_SC_ALL(func)    \
+TEST_SC1_SC1(func)              \
+TEST_SC2_SC2(func)              \
+TEST_SC3_SC3(func)              \
+TEST_SC4_SC4(func)
+#define TEST_UC_UC_ALL(func)    \
+TEST_UC1_UC1(func)              \
+TEST_UC2_UC2(func)              \
+TEST_UC3_UC3(func)              \
+TEST_UC4_UC4(func)
+
+#define TEST_SS_SS_ALL(func)    \
+TEST_SS1_SS1(func)              \
+TEST_SS2_SS2(func)              \
+TEST_SS3_SS3(func)              \
+TEST_SS4_SS4(func)
+#define TEST_US_US_ALL(func)    \
+TEST_US1_US1(func)              \
+TEST_US2_US2(func)              \
+TEST_US3_US3(func)              \
+TEST_US4_US4(func)
+#define TEST_SI_SI_ALL(func)    \
+TEST_SI1_SI1(func)              \
+TEST_SI2_SI2(func)              \
+TEST_SI3_SI3(func)              \
+TEST_SI4_SI4(func)
+#define TEST_UI_UI_ALL(func)    \
+TEST_UI1_UI1(func)              \
+TEST_UI2_UI2(func)              \
+TEST_UI3_UI3(func)              \
+TEST_UI4_UI4(func)
+#define TEST_SL_SL_ALL(func)    \
+TEST_SL1_SL1(func)              \
+TEST_SL2_SL2(func)              \
+TEST_SL3_SL3(func)              \
+TEST_SL4_SL4(func)
+#define TEST_UL_UL_ALL(func)    \
+TEST_UL1_UL1(func)              \
+TEST_UL2_UL2(func)              \
+TEST_UL3_UL3(func)              \
+TEST_UL4_UL4(func)
+
+#define TEST_VEC_VEC_ALL(func)  \
+TEST_FN_FN_ALL(func)            \
+TEST_SC_SC_ALL(func)            \
+TEST_UC_UC_ALL(func)            \
+TEST_SS_SS_ALL(func)            \
+TEST_US_US_ALL(func)            \
+TEST_SI_SI_ALL(func)            \
+TEST_UI_UI_ALL(func)
+
+// TODO:  add long types to ALL macro
+#if 0
+TEST_SL_SL_ALL(func)            \
+TEST_UL_UL_ALL(func)
+#endif
+
+#define DECLARE_TEMP_SET(type, abbrev)  \
+volatile type    temp_##abbrev##1;               \
+volatile type##2 temp_##abbrev##2;               \
+volatile type##3 temp_##abbrev##3;               \
+volatile type##4 temp_##abbrev##4;
+
+#define DECLARE_ALL_TEMP_SETS() \
+DECLARE_TEMP_SET(float, f);     \
+DECLARE_TEMP_SET(char, sc);     \
+DECLARE_TEMP_SET(uchar, uc);    \
+DECLARE_TEMP_SET(short, ss);    \
+DECLARE_TEMP_SET(ushort, us);   \
+DECLARE_TEMP_SET(int, si);      \
+DECLARE_TEMP_SET(uint, ui);     \
+DECLARE_TEMP_SET(long, sl);     \
+DECLARE_TEMP_SET(ulong, ul);
+
+static bool test_math_agree() {
+    bool failed = false;
+
+    DECLARE_ALL_TEMP_SETS();
+
+    TEST_BASIC_FLOAT_OP(+, add);
+    TEST_BASIC_FLOAT_OP(-, sub);
+    TEST_BASIC_FLOAT_OP(*, mul);
+    TEST_BASIC_FLOAT_OP(/, div);
+
+    TEST_VEC_VEC_ALL(min);
+    TEST_VEC_VEC_ALL(max);
+    TEST_FN_FN_ALL(fmin);
+    TEST_FN_F_ALL(fmin);
+    TEST_FN_FN_ALL(fmax);
+    TEST_FN_F_ALL(fmax);
+
+    if (failed) {
+        rsDebug("test_math_agree FAILED", 0);
+    }
+    else {
+        rsDebug("test_math_agree PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_agree_test() {
+    bool failed = false;
+    failed |= test_math_agree();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math_conformance.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math_conformance.rs
new file mode 100644
index 0000000..2d62f34
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math_conformance.rs
@@ -0,0 +1,57 @@
+#include "shared.rsh"
+
+// Testing math conformance
+
+static bool test_rootn() {
+    bool failed = false;
+
+    // rootn(x, 0) -> NaN
+    _RS_ASSERT(isnan(rootn(1.0f, 0)));
+
+    // rootn(+/-0, n) -> +/-inf for odd n < 0
+    _RS_ASSERT(isposinf(rootn(0.f, -3)));
+    _RS_ASSERT(isneginf(rootn(-0.f, -3)));
+
+    // rootn(+/-0, n) -> +inf for even n < 0
+    _RS_ASSERT(isposinf(rootn(0.f, -8)));
+    _RS_ASSERT(isposinf(rootn(-0.f, -8)));
+
+    // rootn(+/-0, n) -> +/-0 for odd n > 0
+    _RS_ASSERT(isposzero(rootn(0.f, 3)));
+    _RS_ASSERT(isnegzero(rootn(-0.f, 3)));
+
+    // rootn(+/-0, n) -> +0 for even n > 0
+    _RS_ASSERT(isposzero(rootn(0.f, 8)));
+    _RS_ASSERT(isposzero(rootn(-0.f, 8)));
+
+    // rootn(x, n) -> NaN for x < 0 and even n
+    _RS_ASSERT(isnan(rootn(-10000.f, -4)));
+    _RS_ASSERT(isnan(rootn(-10000.f, 4)));
+
+    // rootn(x, n) -> value for x < 0 and odd n
+    _RS_ASSERT(!isnan(rootn(-10000.f, -3)));
+    _RS_ASSERT(!isnan(rootn(-10000.f, 3)));
+
+    if (failed) {
+        rsDebug("test_rootn FAILED", -1);
+    }
+    else {
+        rsDebug("test_rootn PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_conformance_test() {
+    bool failed = false;
+    failed |= test_rootn();
+
+    if (failed) {
+        rsDebug("math_conformance_test FAILED", -1);
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsDebug("math_conformance_test PASSED", 0);
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/min.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/min.rs
new file mode 100644
index 0000000..4b92763
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/min.rs
@@ -0,0 +1,20 @@
+#include "shared.rsh"
+#pragma rs_fp_relaxed
+
+volatile uchar2 res_uc_2 = 1;
+volatile uchar2 src1_uc_2 = 1;
+volatile uchar2 src2_uc_2 = 1;
+
+void min_test() {
+    bool failed = false;
+
+    res_uc_2 = min(src1_uc_2, src2_uc_2);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs
new file mode 100644
index 0000000..33944aa
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs
@@ -0,0 +1,44 @@
+#include "shared.rsh"
+
+int *a;
+int dimX;
+int dimY;
+static bool failed = false;
+
+void foo(const int *in, int *out, uint32_t x, uint32_t y) {
+    *out = 99 + x + y * dimX;
+}
+
+static bool test_foo_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            _RS_ASSERT(a[i + j * dimX] == (99 + i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_foo_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_foo_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_foo() {
+    failed |= test_foo_output();
+}
+
+void noroot_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/primitives.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/primitives.rs
new file mode 100644
index 0000000..ce451da
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/primitives.rs
@@ -0,0 +1,61 @@
+#include "shared.rsh"
+
+// Testing primitive types
+float floatTest = 1.99f;
+double doubleTest = 2.05;
+char charTest = -8;
+short shortTest = -16;
+int intTest = -32;
+long longTest = 17179869184l; // 1 << 34
+long long longlongTest = 68719476736l; // 1 << 36
+
+uchar ucharTest = 8;
+ushort ushortTest = 16;
+uint uintTest = 32;
+ulong ulongTest = 4611686018427387904L;
+int64_t int64_tTest = -17179869184l; // - 1 << 34
+uint64_t uint64_tTest = 117179869184l;
+
+static bool test_primitive_types(uint32_t index) {
+    bool failed = false;
+    start();
+
+    _RS_ASSERT(floatTest == 2.99f);
+    _RS_ASSERT(doubleTest == 3.05);
+    _RS_ASSERT(charTest == -16);
+    _RS_ASSERT(shortTest == -32);
+    _RS_ASSERT(intTest == -64);
+    _RS_ASSERT(longTest == 17179869185l);
+    _RS_ASSERT(longlongTest == 68719476735l);
+
+    _RS_ASSERT(ucharTest == 8);
+    _RS_ASSERT(ushortTest == 16);
+    _RS_ASSERT(uintTest == 32);
+    _RS_ASSERT(ulongTest == 4611686018427387903L);
+    _RS_ASSERT(int64_tTest == -17179869184l);
+    _RS_ASSERT(uint64_tTest == 117179869185l);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_primitives FAILED", time);
+    }
+    else {
+        rsDebug("test_primitives PASSED", time);
+    }
+
+    return failed;
+}
+
+void primitives_test(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= test_primitive_types(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/refcount.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/refcount.rs
new file mode 100644
index 0000000..4ea70e2
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/refcount.rs
@@ -0,0 +1,13 @@
+#include "shared.rsh"
+
+// Testing reference counting of RS object types
+
+rs_allocation globalA;
+static rs_allocation staticGlobalA;
+
+void refcount_test() {
+    staticGlobalA = globalA;
+    rsClearObject(&globalA);
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rsdebug.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rsdebug.rs
new file mode 100644
index 0000000..68ac168
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rsdebug.rs
@@ -0,0 +1,62 @@
+#include "shared.rsh"
+
+// Testing primitive types
+float floatTest = 1.99f;
+float2 float2Test = {2.99f, 12.99f};
+float3 float3Test = {3.99f, 13.99f, 23.99f};
+float4 float4Test = {4.99f, 14.99f, 24.99f, 34.99f};
+double doubleTest = 2.05;
+char charTest = -8;
+short shortTest = -16;
+int intTest = -32;
+long longTest = 17179869184l; // 1 << 34
+long long longlongTest = 68719476736l; // 1 << 36
+
+uchar ucharTest = 8;
+ushort ushortTest = 16;
+uint uintTest = 32;
+ulong ulongTest = 4611686018427387904L;
+int64_t int64_tTest = -17179869184l; // - 1 << 34
+uint64_t uint64_tTest = 117179869184l;
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    // This test focuses primarily on compilation-time, not run-time.
+    // For this reason, none of the outputs are actually checked.
+
+    rsDebug("floatTest", floatTest);
+    rsDebug("float2Test", float2Test);
+    rsDebug("float3Test", float3Test);
+    rsDebug("float4Test", float4Test);
+    rsDebug("doubleTest", doubleTest);
+    rsDebug("charTest", charTest);
+    rsDebug("shortTest", shortTest);
+    rsDebug("intTest", intTest);
+    rsDebug("longTest", longTest);
+    rsDebug("longlongTest", longlongTest);
+
+    rsDebug("ucharTest", ucharTest);
+    rsDebug("ushortTest", ushortTest);
+    rsDebug("uintTest", uintTest);
+    rsDebug("ulongTest", ulongTest);
+    rsDebug("int64_tTest", int64_tTest);
+    rsDebug("uint64_tTest", uint64_tTest);
+
+    return failed;
+}
+
+void test_rsdebug(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rsdebug_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rsdebug_test PASSED", 0);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rslist.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rslist.rs
new file mode 100644
index 0000000..650243e
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rslist.rs
@@ -0,0 +1,25 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_compat)
+
+typedef struct ListAllocs_s {
+    rs_allocation text;
+    int result;
+} ListAllocs;
+
+ListAllocs *gList;
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rstime.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rstime.rs
new file mode 100644
index 0000000..7be955d
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rstime.rs
@@ -0,0 +1,52 @@
+#include "shared.rsh"
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_time_t curTime = rsTime(0);
+    rs_tm tm;
+    rsDebug("curTime", curTime);
+
+    rsLocaltime(&tm, &curTime);
+
+    rsDebug("tm.tm_sec", tm.tm_sec);
+    rsDebug("tm.tm_min", tm.tm_min);
+    rsDebug("tm.tm_hour", tm.tm_hour);
+    rsDebug("tm.tm_mday", tm.tm_mday);
+    rsDebug("tm.tm_mon", tm.tm_mon);
+    rsDebug("tm.tm_year", tm.tm_year);
+    rsDebug("tm.tm_wday", tm.tm_wday);
+    rsDebug("tm.tm_yday", tm.tm_yday);
+    rsDebug("tm.tm_isdst", tm.tm_isdst);
+
+    // Test a specific time (since we set America/Los_Angeles localtime)
+    curTime = 1294438893;
+    rsLocaltime(&tm, &curTime);
+
+    _RS_ASSERT(tm.tm_sec == 33);
+    _RS_ASSERT(tm.tm_min == 21);
+    _RS_ASSERT(tm.tm_hour == 14);
+    _RS_ASSERT(tm.tm_mday == 7);
+    _RS_ASSERT(tm.tm_mon == 0);
+    _RS_ASSERT(tm.tm_year == 111);
+    _RS_ASSERT(tm.tm_wday == 5);
+    _RS_ASSERT(tm.tm_yday == 6);
+    _RS_ASSERT(tm.tm_isdst == 0);
+
+    return failed;
+}
+
+void test_rstime(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstime_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstime_test PASSED", 0);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rstypes.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rstypes.rs
new file mode 100644
index 0000000..bec124d
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rstypes.rs
@@ -0,0 +1,61 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_element elementTest;
+rs_type typeTest;
+rs_allocation allocationTest;
+rs_sampler samplerTest;
+rs_script scriptTest;
+
+rs_matrix4x4 matrix4x4Test;
+rs_matrix3x3 matrix3x3Test;
+rs_matrix2x2 matrix2x2Test;
+
+struct my_struct {
+    int i;
+    rs_allocation banana;
+};
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_matrix4x4 matrix4x4TestLocal;
+    rs_matrix3x3 matrix3x3TestLocal;
+    rs_matrix2x2 matrix2x2TestLocal;
+
+    // This test focuses primarily on compilation-time, not run-time.
+    rs_element elementTestLocal;
+    rs_type typeTestLocal;
+    rs_allocation allocationTestLocal;
+    rs_sampler samplerTestLocal;
+    rs_script scriptTestLocal;
+
+    struct my_struct structTest;
+
+    //allocationTestLocal = allocationTest;
+
+    //allocationTest = allocationTestLocal;
+
+    /*for (int i = 0; i < 4; i++) {
+        fontTestLocalArray[i] = fontTestLocal;
+    }*/
+
+    /*fontTest = fontTestLocalArray[3];*/
+
+    return failed;
+}
+
+void test_rstypes(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstypes_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstypes_test PASSED", 0);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/sampler.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/sampler.rs
new file mode 100644
index 0000000..ff1c0a7
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/sampler.rs
@@ -0,0 +1,63 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+rs_sampler minification;
+rs_sampler magnification;
+rs_sampler wrapS;
+rs_sampler wrapT;
+rs_sampler anisotropy;
+
+static bool test_sampler_getters() {
+    bool failed = false;
+
+    _RS_ASSERT(rsSamplerGetMagnification(minification) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(minification) == RS_SAMPLER_LINEAR_MIP_LINEAR);
+    _RS_ASSERT(rsSamplerGetWrapS(minification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(minification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(minification) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(magnification) == RS_SAMPLER_LINEAR);
+    _RS_ASSERT(rsSamplerGetMinification(magnification) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(magnification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(magnification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(magnification) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(wrapS) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(wrapS) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(wrapS) == RS_SAMPLER_WRAP);
+    _RS_ASSERT(rsSamplerGetWrapT(wrapS) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(wrapS) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(wrapT) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(wrapT) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(wrapT) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(wrapT) == RS_SAMPLER_WRAP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(wrapT) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(anisotropy) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(anisotropy) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(anisotropy) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(anisotropy) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(anisotropy) == 8.0f);
+
+    if (failed) {
+        rsDebug("test_sampler_getters FAILED", 0);
+    }
+    else {
+        rsDebug("test_sampler_getters PASSED", 0);
+    }
+
+    return failed;
+}
+
+void sampler_test() {
+    bool failed = false;
+    failed |= test_sampler_getters();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/shared.rsh b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/shared.rsh
new file mode 100644
index 0000000..b05a354
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/shared.rsh
@@ -0,0 +1,114 @@
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_compat)
+
+typedef struct TestResult_s {
+    rs_allocation name;
+    bool pass;
+    float score;
+    int64_t time;
+} TestResult;
+//TestResult *g_results;
+
+static int64_t g_time;
+
+static void start(void) {
+    g_time = rsUptimeMillis();
+}
+
+static float end(uint32_t idx) {
+    int64_t t = rsUptimeMillis() - g_time;
+    //g_results[idx].time = t;
+    //rsDebug("test time", (int)t);
+    return ((float)t) / 1000.f;
+}
+
+#define _RS_ASSERT(b) \
+do { \
+    if (!(b)) { \
+        failed = true; \
+        rsDebug(#b " FAILED", 0); \
+    } \
+\
+} while (0)
+
+static const int iposinf = 0x7f800000;
+static const int ineginf = 0xff800000;
+
+static const float posinf() {
+    float f = *((float*)&iposinf);
+    return f;
+}
+
+static const float neginf() {
+    float f = *((float*)&ineginf);
+    return f;
+}
+
+static bool isposinf(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == iposinf);
+}
+
+static bool isneginf(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == ineginf);
+}
+
+static bool isnan(float f) {
+    int i = *((int*)(void*)&f);
+    return (((i & 0x7f800000) == 0x7f800000) && (i & 0x007fffff));
+}
+
+static bool isposzero(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == 0x00000000);
+}
+
+static bool isnegzero(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == 0x80000000);
+}
+
+static bool iszero(float f) {
+    return isposzero(f) || isnegzero(f);
+}
+
+/* Absolute epsilon used for floats.  Value is similar to float.h. */
+#ifndef FLT_EPSILON
+#define FLT_EPSILON 1.19e7f
+#endif
+/* Max ULPs while still being considered "equal".  Only used when this number
+   of ULPs is of a greater size than FLT_EPSILON. */
+#define FLT_MAX_ULP 1
+
+/* Calculate the difference in ULPs between the two values.  (Return zero on
+   perfect equality.) */
+static int float_dist(float f1, float f2) {
+    return *((int *)(&f1)) - *((int *)(&f2));
+}
+
+/* Check if two floats are essentially equal.  Will fail with some values
+   due to design.  (Validate using FLT_EPSILON or similar if necessary.) */
+static bool float_almost_equal(float f1, float f2) {
+    int *i1 = (int*)(&f1);
+    int *i2 = (int*)(&f2);
+
+    // Check for sign equality
+    if ( ((*i1 >> 31) == 0) != ((*i2 >> 31) == 0) ) {
+        // Handle signed zeroes
+        if (f1 == f2)
+            return true;
+        return false;
+    }
+
+    // Check with ULP distance
+    if (float_dist(f1, f2) > FLT_MAX_ULP)
+        return false;
+    return true;
+}
+
+/* These constants must match those in UnitTest.java */
+static const int RS_MSG_TEST_PASSED = 100;
+static const int RS_MSG_TEST_FAILED = 101;
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/struct.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/struct.rs
new file mode 100644
index 0000000..1cd728e
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/struct.rs
@@ -0,0 +1,37 @@
+#include "shared.rsh"
+
+typedef struct Point2 {
+   int x;
+   int y;
+} Point_2;
+Point_2 *point2;
+
+static bool test_Point_2(int expected) {
+    bool failed = false;
+
+    rsDebug("Point: ", point2[0].x, point2[0].y);
+    _RS_ASSERT(point2[0].x == expected);
+    _RS_ASSERT(point2[0].y == expected);
+
+    if (failed) {
+        rsDebug("test_Point_2 FAILED", 0);
+    }
+    else {
+        rsDebug("test_Point_2 PASSED", 0);
+    }
+
+    return failed;
+}
+
+void struct_test(int expected) {
+    bool failed = false;
+    failed |= test_Point_2(expected);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/test_root.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/test_root.rs
new file mode 100644
index 0000000..89e7de7
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/test_root.rs
@@ -0,0 +1,23 @@
+// Fountain test script
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_compat)
+
+#pragma stateFragment(parent)
+
+#include "rs_graphics.rsh"
+
+
+typedef struct TestResult {
+    rs_allocation name;
+    bool pass;
+    float score;
+} TestResult_t;
+TestResult_t *results;
+
+int root() {
+
+    return 0;
+}
+
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/unsigned.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/unsigned.rs
new file mode 100644
index 0000000..2c056f4
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/unsigned.rs
@@ -0,0 +1,36 @@
+#include "shared.rsh"
+
+// Testing unsigned types for Bug 6764163
+unsigned int ui = 37;
+unsigned char uc = 5;
+
+static bool test_unsigned() {
+    bool failed = false;
+
+    rsDebug("ui", ui);
+    rsDebug("uc", uc);
+    _RS_ASSERT(ui == 0x7fffffff);
+    _RS_ASSERT(uc == 129);
+
+    if (failed) {
+        rsDebug("test_unsigned FAILED", -1);
+    }
+    else {
+        rsDebug("test_unsigned PASSED", 0);
+    }
+
+    return failed;
+}
+
+void unsigned_test() {
+    bool failed = false;
+    failed |= test_unsigned();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/vector.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/vector.rs
new file mode 100644
index 0000000..0430a2f
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/vector.rs
@@ -0,0 +1,198 @@
+#include "shared.rsh"
+
+// Testing vector types
+float2 f2 = { 1.0f, 2.0f };
+float3 f3 = { 1.0f, 2.0f, 3.0f };
+float4 f4 = { 1.0f, 2.0f, 3.0f, 4.0f };
+
+double2 d2 = { 1.0, 2.0 };
+double3 d3 = { 1.0, 2.0, 3.0 };
+double4 d4 = { 1.0, 2.0, 3.0, 4.0 };
+
+char2 i8_2 = { 1, 2 };
+char3 i8_3 = { 1, 2, 3 };
+char4 i8_4 = { 1, 2, 3, 4 };
+
+uchar2 u8_2 = { 1, 2 };
+uchar3 u8_3 = { 1, 2, 3 };
+uchar4 u8_4 = { 1, 2, 3, 4 };
+
+short2 i16_2 = { 1, 2 };
+short3 i16_3 = { 1, 2, 3 };
+short4 i16_4 = { 1, 2, 3, 4 };
+
+ushort2 u16_2 = { 1, 2 };
+ushort3 u16_3 = { 1, 2, 3 };
+ushort4 u16_4 = { 1, 2, 3, 4 };
+
+int2 i32_2 = { 1, 2 };
+int3 i32_3 = { 1, 2, 3 };
+int4 i32_4 = { 1, 2, 3, 4 };
+
+uint2 u32_2 = { 1, 2 };
+uint3 u32_3 = { 1, 2, 3 };
+uint4 u32_4 = { 1, 2, 3, 4 };
+
+long2 i64_2 = { 1, 2 };
+long3 i64_3 = { 1, 2, 3 };
+long4 i64_4 = { 1, 2, 3, 4 };
+
+ulong2 u64_2 = { 1, 2 };
+ulong3 u64_3 = { 1, 2, 3 };
+ulong4 u64_4 = { 1, 2, 3, 4 };
+
+static bool test_vector_types() {
+    bool failed = false;
+
+    rsDebug("Testing F32", 0);
+    _RS_ASSERT(f2.x == 2.99f);
+    _RS_ASSERT(f2.y == 3.99f);
+
+    _RS_ASSERT(f3.x == 2.99f);
+    _RS_ASSERT(f3.y == 3.99f);
+    _RS_ASSERT(f3.z == 4.99f);
+
+    _RS_ASSERT(f4.x == 2.99f);
+    _RS_ASSERT(f4.y == 3.99f);
+    _RS_ASSERT(f4.z == 4.99f);
+    _RS_ASSERT(f4.w == 5.99f);
+
+    rsDebug("Testing F64", 0);
+    _RS_ASSERT(d2.x == 2.99);
+    _RS_ASSERT(d2.y == 3.99);
+
+    _RS_ASSERT(d3.x == 2.99);
+    _RS_ASSERT(d3.y == 3.99);
+    _RS_ASSERT(d3.z == 4.99);
+
+    _RS_ASSERT(d4.x == 2.99);
+    _RS_ASSERT(d4.y == 3.99);
+    _RS_ASSERT(d4.z == 4.99);
+    _RS_ASSERT(d4.w == 5.99);
+
+    rsDebug("Testing I8", 0);
+    _RS_ASSERT(i8_2.x == 2);
+    _RS_ASSERT(i8_2.y == 3);
+
+    _RS_ASSERT(i8_3.x == 2);
+    _RS_ASSERT(i8_3.y == 3);
+    _RS_ASSERT(i8_3.z == 4);
+
+    _RS_ASSERT(i8_4.x == 2);
+    _RS_ASSERT(i8_4.y == 3);
+    _RS_ASSERT(i8_4.z == 4);
+    _RS_ASSERT(i8_4.w == 5);
+
+    rsDebug("Testing U8", 0);
+    _RS_ASSERT(u8_2.x == 2);
+    _RS_ASSERT(u8_2.y == 3);
+
+    _RS_ASSERT(u8_3.x == 2);
+    _RS_ASSERT(u8_3.y == 3);
+    _RS_ASSERT(u8_3.z == 4);
+
+    _RS_ASSERT(u8_4.x == 2);
+    _RS_ASSERT(u8_4.y == 3);
+    _RS_ASSERT(u8_4.z == 4);
+    _RS_ASSERT(u8_4.w == 5);
+
+    rsDebug("Testing I16", 0);
+    _RS_ASSERT(i16_2.x == 2);
+    _RS_ASSERT(i16_2.y == 3);
+
+    _RS_ASSERT(i16_3.x == 2);
+    _RS_ASSERT(i16_3.y == 3);
+    _RS_ASSERT(i16_3.z == 4);
+
+    _RS_ASSERT(i16_4.x == 2);
+    _RS_ASSERT(i16_4.y == 3);
+    _RS_ASSERT(i16_4.z == 4);
+    _RS_ASSERT(i16_4.w == 5);
+
+    rsDebug("Testing U16", 0);
+    _RS_ASSERT(u16_2.x == 2);
+    _RS_ASSERT(u16_2.y == 3);
+
+    _RS_ASSERT(u16_3.x == 2);
+    _RS_ASSERT(u16_3.y == 3);
+    _RS_ASSERT(u16_3.z == 4);
+
+    _RS_ASSERT(u16_4.x == 2);
+    _RS_ASSERT(u16_4.y == 3);
+    _RS_ASSERT(u16_4.z == 4);
+    _RS_ASSERT(u16_4.w == 5);
+
+    rsDebug("Testing I32", 0);
+    _RS_ASSERT(i32_2.x == 2);
+    _RS_ASSERT(i32_2.y == 3);
+
+    _RS_ASSERT(i32_3.x == 2);
+    _RS_ASSERT(i32_3.y == 3);
+    _RS_ASSERT(i32_3.z == 4);
+
+    _RS_ASSERT(i32_4.x == 2);
+    _RS_ASSERT(i32_4.y == 3);
+    _RS_ASSERT(i32_4.z == 4);
+    _RS_ASSERT(i32_4.w == 5);
+
+    rsDebug("Testing U32", 0);
+    _RS_ASSERT(u32_2.x == 2);
+    _RS_ASSERT(u32_2.y == 3);
+
+    _RS_ASSERT(u32_3.x == 2);
+    _RS_ASSERT(u32_3.y == 3);
+    _RS_ASSERT(u32_3.z == 4);
+
+    _RS_ASSERT(u32_4.x == 2);
+    _RS_ASSERT(u32_4.y == 3);
+    _RS_ASSERT(u32_4.z == 4);
+    _RS_ASSERT(u32_4.w == 5);
+
+    rsDebug("Testing I64", 0);
+    _RS_ASSERT(i64_2.x == 2);
+    _RS_ASSERT(i64_2.y == 3);
+
+    _RS_ASSERT(i64_3.x == 2);
+    _RS_ASSERT(i64_3.y == 3);
+    _RS_ASSERT(i64_3.z == 4);
+
+    _RS_ASSERT(i64_4.x == 2);
+    _RS_ASSERT(i64_4.y == 3);
+    _RS_ASSERT(i64_4.z == 4);
+    _RS_ASSERT(i64_4.w == 5);
+
+    rsDebug("Testing U64", 0);
+    _RS_ASSERT(u64_2.x == 2);
+    _RS_ASSERT(u64_2.y == 3);
+
+    _RS_ASSERT(u64_3.x == 2);
+    _RS_ASSERT(u64_3.y == 3);
+    _RS_ASSERT(u64_3.z == 4);
+
+    _RS_ASSERT(u64_4.x == 2);
+    _RS_ASSERT(u64_4.y == 3);
+    _RS_ASSERT(u64_4.z == 4);
+    _RS_ASSERT(u64_4.w == 5);
+
+    if (failed) {
+        rsDebug("test_vector FAILED", 0);
+    }
+    else {
+        rsDebug("test_vector PASSED", 0);
+    }
+
+    return failed;
+}
+
+void vector_test() {
+    bool failed = false;
+    failed |= test_vector_types();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/math.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/math.rs
index aae29a4..edde9d8 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/math.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/math.rs
@@ -278,6 +278,7 @@
     TEST_FN_FUNC_FN_F(fmin);
     TEST_FN_FUNC_FN_FN(fmod);
     TEST_FN_FUNC_FN_PFN(fract);
+    TEST_FN_FUNC_FN(fract);
     TEST_FN_FUNC_FN_PIN(frexp);
     TEST_FN_FUNC_FN_FN(hypot);
     TEST_IN_FUNC_FN(ilogb);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index e2fced6..e682da7 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -1080,6 +1080,12 @@
     }
 
     @Override
+    public String getBasePackageName() {
+        // pass
+        return null;
+    }
+
+    @Override
     public ApplicationInfo getApplicationInfo() {
         return mApplicationInfo;
     }
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index 1d67055..ea943e9 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -25,17 +25,11 @@
 import android.net.sip.SimpleSessionDescription.Media;
 import android.net.wifi.WifiManager;
 import android.os.Message;
-import android.os.RemoteException;
+import android.telephony.Rlog;
 import android.text.TextUtils;
-import android.util.Log;
-
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
 
 /**
  * Handles an Internet audio call over SIP. You can instantiate this class with {@link SipManager},
@@ -60,7 +54,8 @@
  * </div>
  */
 public class SipAudioCall {
-    private static final String TAG = SipAudioCall.class.getSimpleName();
+    private static final String LOG_TAG = SipAudioCall.class.getSimpleName();
+    private static final boolean DBG = true;
     private static final boolean RELEASE_SOCKET = true;
     private static final boolean DONT_RELEASE_SOCKET = false;
     private static final int SESSION_TIMEOUT = 5; // in seconds
@@ -191,7 +186,6 @@
     private boolean mMuted = false;
     private boolean mHold = false;
 
-    private SipProfile mPendingCallRequest;
     private WifiManager mWm;
     private WifiManager.WifiLock mWifiHighPerfLock;
 
@@ -261,7 +255,7 @@
                 }
             }
         } catch (Throwable t) {
-            Log.e(TAG, "setListener()", t);
+            loge("setListener()", t);
         }
     }
 
@@ -371,7 +365,7 @@
                 mAudioStream = new AudioStream(InetAddress.getByName(
                         getLocalIp()));
             } catch (Throwable t) {
-                Log.i(TAG, "transferToNewSession(): " + t);
+                loge("transferToNewSession():", t);
             }
         }
         if (origin != null) origin.endCall();
@@ -382,26 +376,26 @@
         return new SipSession.Listener() {
             @Override
             public void onCalling(SipSession session) {
-                Log.d(TAG, "calling... " + session);
+                if (DBG) log("onCalling: session=" + session);
                 Listener listener = mListener;
                 if (listener != null) {
                     try {
                         listener.onCalling(SipAudioCall.this);
                     } catch (Throwable t) {
-                        Log.i(TAG, "onCalling(): " + t);
+                        loge("onCalling():", t);
                     }
                 }
             }
 
             @Override
             public void onRingingBack(SipSession session) {
-                Log.d(TAG, "sip call ringing back: " + session);
+                if (DBG) log("onRingingBackk: " + session);
                 Listener listener = mListener;
                 if (listener != null) {
                     try {
                         listener.onRingingBack(SipAudioCall.this);
                     } catch (Throwable t) {
-                        Log.i(TAG, "onRingingBack(): " + t);
+                        loge("onRingingBack():", t);
                     }
                 }
             }
@@ -424,7 +418,7 @@
                         String answer = createAnswer(sessionDescription).encode();
                         mSipSession.answerCall(answer, SESSION_TIMEOUT);
                     } catch (Throwable e) {
-                        Log.e(TAG, "onRinging()", e);
+                        loge("onRinging():", e);
                         session.endCall();
                     }
                 }
@@ -434,7 +428,7 @@
             public void onCallEstablished(SipSession session,
                     String sessionDescription) {
                 mPeerSd = sessionDescription;
-                Log.v(TAG, "onCallEstablished()" + mPeerSd);
+                if (DBG) log("onCallEstablished(): " + mPeerSd);
 
                 // TODO: how to notify the UI that the remote party is changed
                 if ((mTransferringSession != null)
@@ -452,14 +446,14 @@
                             listener.onCallEstablished(SipAudioCall.this);
                         }
                     } catch (Throwable t) {
-                        Log.i(TAG, "onCallEstablished(): " + t);
+                        loge("onCallEstablished(): ", t);
                     }
                 }
             }
 
             @Override
             public void onCallEnded(SipSession session) {
-                Log.d(TAG, "sip call ended: " + session + " mSipSession:" + mSipSession);
+                if (DBG) log("onCallEnded: " + session + " mSipSession:" + mSipSession);
                 // reset the trasnferring session if it is the one.
                 if (session == mTransferringSession) {
                     mTransferringSession = null;
@@ -475,7 +469,7 @@
                     try {
                         listener.onCallEnded(SipAudioCall.this);
                     } catch (Throwable t) {
-                        Log.i(TAG, "onCallEnded(): " + t);
+                        loge("onCallEnded(): ", t);
                     }
                 }
                 close();
@@ -483,13 +477,13 @@
 
             @Override
             public void onCallBusy(SipSession session) {
-                Log.d(TAG, "sip call busy: " + session);
+                if (DBG) log("onCallBusy: " + session);
                 Listener listener = mListener;
                 if (listener != null) {
                     try {
                         listener.onCallBusy(SipAudioCall.this);
                     } catch (Throwable t) {
-                        Log.i(TAG, "onCallBusy(): " + t);
+                        loge("onCallBusy(): ", t);
                     }
                 }
                 close(false);
@@ -498,7 +492,7 @@
             @Override
             public void onCallChangeFailed(SipSession session, int errorCode,
                     String message) {
-                Log.d(TAG, "sip call change failed: " + message);
+                if (DBG) log("onCallChangedFailed: " + message);
                 mErrorCode = errorCode;
                 mErrorMessage = message;
                 Listener listener = mListener;
@@ -507,7 +501,7 @@
                         listener.onError(SipAudioCall.this, mErrorCode,
                                 message);
                     } catch (Throwable t) {
-                        Log.i(TAG, "onCallBusy(): " + t);
+                        loge("onCallBusy():", t);
                     }
                 }
             }
@@ -542,8 +536,8 @@
             @Override
             public void onCallTransferring(SipSession newSession,
                     String sessionDescription) {
-                Log.v(TAG, "onCallTransferring mSipSession:"
-                        + mSipSession + " newSession:" + newSession);
+                if (DBG) log("onCallTransferring: mSipSession="
+                        + mSipSession + " newSession=" + newSession);
                 mTransferringSession = newSession;
                 try {
                     if (sessionDescription == null) {
@@ -554,7 +548,7 @@
                         newSession.answerCall(answer, SESSION_TIMEOUT);
                     }
                 } catch (Throwable e) {
-                    Log.e(TAG, "onCallTransferring()", e);
+                    loge("onCallTransferring()", e);
                     newSession.endCall();
                 }
             }
@@ -562,7 +556,7 @@
     }
 
     private void onError(int errorCode, String message) {
-        Log.d(TAG, "sip session error: "
+        if (DBG) log("onError: "
                 + SipErrorCode.toString(errorCode) + ": " + message);
         mErrorCode = errorCode;
         mErrorMessage = message;
@@ -571,7 +565,7 @@
             try {
                 listener.onError(this, errorCode, message);
             } catch (Throwable t) {
-                Log.i(TAG, "onError(): " + t);
+                loge("onError():", t);
             }
         }
         synchronized (this) {
@@ -600,11 +594,11 @@
         synchronized (this) {
             mSipSession = session;
             mPeerSd = sessionDescription;
-            Log.v(TAG, "attachCall()" + mPeerSd);
+            if (DBG) log("attachCall(): " + mPeerSd);
             try {
                 session.setListener(createListener());
             } catch (Throwable e) {
-                Log.e(TAG, "attachCall()", e);
+                loge("attachCall()", e);
                 throwSipException(e);
             }
         }
@@ -627,6 +621,7 @@
      */
     public void makeCall(SipProfile peerProfile, SipSession sipSession,
             int timeout) throws SipException {
+        if (DBG) log("makeCall: " + peerProfile + " session=" + sipSession + " timeout=" + timeout);
         if (!SipManager.isVoipSupported(mContext)) {
             throw new SipException("VOIP API is not supported");
         }
@@ -640,6 +635,7 @@
                 sipSession.makeCall(peerProfile, createOffer().encode(),
                         timeout);
             } catch (IOException e) {
+                loge("makeCall:", e);
                 throw new SipException("makeCall()", e);
             }
         }
@@ -650,6 +646,7 @@
      * @throws SipException if the SIP service fails to end the call
      */
     public void endCall() throws SipException {
+        if (DBG) log("endCall: mSipSession" + mSipSession);
         synchronized (this) {
             stopCall(RELEASE_SOCKET);
             mInCall = false;
@@ -672,9 +669,11 @@
      * @throws SipException if the SIP service fails to hold the call
      */
     public void holdCall(int timeout) throws SipException {
+        if (DBG) log("holdCall: mSipSession" + mSipSession + " timeout=" + timeout);
         synchronized (this) {
             if (mHold) return;
             if (mSipSession == null) {
+                loge("holdCall:");
                 throw new SipException("Not in a call to hold call");
             }
             mSipSession.changeCall(createHoldOffer().encode(), timeout);
@@ -695,6 +694,7 @@
      * @throws SipException if the SIP service fails to answer the call
      */
     public void answerCall(int timeout) throws SipException {
+        if (DBG) log("answerCall: mSipSession" + mSipSession + " timeout=" + timeout);
         synchronized (this) {
             if (mSipSession == null) {
                 throw new SipException("No call to answer");
@@ -704,6 +704,7 @@
                         getLocalIp()));
                 mSipSession.answerCall(createAnswer(mPeerSd).encode(), timeout);
             } catch (IOException e) {
+                loge("answerCall:", e);
                 throw new SipException("answerCall()", e);
             }
         }
@@ -722,6 +723,7 @@
      * @throws SipException if the SIP service fails to unhold the call
      */
     public void continueCall(int timeout) throws SipException {
+        if (DBG) log("continueCall: mSipSession" + mSipSession + " timeout=" + timeout);
         synchronized (this) {
             if (!mHold) return;
             mSipSession.changeCall(createContinueOffer().encode(), timeout);
@@ -740,6 +742,7 @@
             media.setRtpPayload(codec.type, codec.rtpmap, codec.fmtp);
         }
         media.setRtpPayload(127, "telephone-event/8000", "0-15");
+        if (DBG) log("createOffer: offer=" + offer);
         return offer;
     }
 
@@ -798,18 +801,22 @@
             }
         }
         if (codec == null) {
+            loge("createAnswer: no suitable codes");
             throw new IllegalStateException("Reject SDP: no suitable codecs");
         }
+        if (DBG) log("createAnswer: answer=" + answer);
         return answer;
     }
 
     private SimpleSessionDescription createHoldOffer() {
         SimpleSessionDescription offer = createContinueOffer();
         offer.setAttribute("sendonly", "");
+        if (DBG) log("createHoldOffer: offer=" + offer);
         return offer;
     }
 
     private SimpleSessionDescription createContinueOffer() {
+        if (DBG) log("createContinueOffer");
         SimpleSessionDescription offer =
                 new SimpleSessionDescription(mSessionId, getLocalIp());
         Media media = offer.newMedia(
@@ -825,17 +832,17 @@
 
     private void grabWifiHighPerfLock() {
         if (mWifiHighPerfLock == null) {
-            Log.v(TAG, "acquire wifi high perf lock");
+            if (DBG) log("grabWifiHighPerfLock:");
             mWifiHighPerfLock = ((WifiManager)
                     mContext.getSystemService(Context.WIFI_SERVICE))
-                    .createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, TAG);
+                    .createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, LOG_TAG);
             mWifiHighPerfLock.acquire();
         }
     }
 
     private void releaseWifiHighPerfLock() {
         if (mWifiHighPerfLock != null) {
-            Log.v(TAG, "release wifi high perf lock");
+            if (DBG) log("releaseWifiHighPerfLock:");
             mWifiHighPerfLock.release();
             mWifiHighPerfLock = null;
         }
@@ -912,7 +919,7 @@
             AudioGroup audioGroup = getAudioGroup();
             if ((audioGroup != null) && (mSipSession != null)
                     && (SipSession.State.IN_CALL == getState())) {
-                Log.v(TAG, "send DTMF: " + code);
+                if (DBG) log("sendDtmf: code=" + code + " result=" + result);
                 audioGroup.sendDtmf(code);
             }
             if (result != null) result.sendToTarget();
@@ -971,6 +978,7 @@
      */
     public void setAudioGroup(AudioGroup group) {
         synchronized (this) {
+            if (DBG) log("setAudioGroup: group=" + group);
             if ((mAudioStream != null) && (mAudioStream.getGroup() != null)) {
                 mAudioStream.join(group);
             }
@@ -997,8 +1005,8 @@
     }
 
     private synchronized void startAudioInternal() throws UnknownHostException {
+        if (DBG) loge("startAudioInternal: mPeerSd=" + mPeerSd);
         if (mPeerSd == null) {
-            Log.v(TAG, "startAudioInternal() mPeerSd = null");
             throw new IllegalStateException("mPeerSd = null");
         }
 
@@ -1082,6 +1090,7 @@
     // set audio group mode based on current audio configuration
     private void setAudioGroupMode() {
         AudioGroup audioGroup = getAudioGroup();
+        if (DBG) log("setAudioGroupMode: audioGroup=" + audioGroup);
         if (audioGroup != null) {
             if (mHold) {
                 audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
@@ -1096,7 +1105,7 @@
     }
 
     private void stopCall(boolean releaseSocket) {
-        Log.d(TAG, "stop audiocall");
+        if (DBG) log("stopCall: releaseSocket=" + releaseSocket);
         releaseWifiHighPerfLock();
         if (mAudioStream != null) {
             mAudioStream.join(null);
@@ -1120,7 +1129,15 @@
         }
     }
 
-    private SipProfile getPeerProfile(SipSession session) {
-        return session.getPeerProfile();
+    private void log(String s) {
+        Rlog.d(LOG_TAG, s);
+    }
+
+    private void loge(String s) {
+        Rlog.e(LOG_TAG, s);
+    }
+
+    private void loge(String s, Throwable t) {
+        Rlog.e(LOG_TAG, s, t);
     }
 }
diff --git a/voip/java/android/net/sip/SipManager.java b/voip/java/android/net/sip/SipManager.java
index 74c3672..a94232a 100644
--- a/voip/java/android/net/sip/SipManager.java
+++ b/voip/java/android/net/sip/SipManager.java
@@ -21,10 +21,9 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.util.Log;
+import android.telephony.Rlog;
 
 import java.text.ParseException;
 
@@ -591,7 +590,7 @@
                         : session.getLocalProfile().getUriString());
             } catch (Throwable e) {
                 // SipService died? SIP stack died?
-                Log.w(TAG, "getUri(): " + e);
+                Rlog.e(TAG, "getUri(): ", e);
                 return null;
             }
         }
diff --git a/voip/java/android/net/sip/SipSession.java b/voip/java/android/net/sip/SipSession.java
index e03cf9f..edbc66f 100644
--- a/voip/java/android/net/sip/SipSession.java
+++ b/voip/java/android/net/sip/SipSession.java
@@ -17,7 +17,7 @@
 package android.net.sip;
 
 import android.os.RemoteException;
-import android.util.Log;
+import android.telephony.Rlog;
 
 /**
  * Represents a SIP session that is associated with a SIP dialog or a standalone
@@ -242,7 +242,7 @@
             try {
                 realSession.setListener(createListener());
             } catch (RemoteException e) {
-                Log.e(TAG, "SipSession.setListener(): " + e);
+                loge("SipSession.setListener:", e);
             }
         }
     }
@@ -261,7 +261,7 @@
         try {
             return mSession.getLocalIp();
         } catch (RemoteException e) {
-            Log.e(TAG, "getLocalIp(): " + e);
+            loge("getLocalIp:", e);
             return "127.0.0.1";
         }
     }
@@ -275,7 +275,7 @@
         try {
             return mSession.getLocalProfile();
         } catch (RemoteException e) {
-            Log.e(TAG, "getLocalProfile(): " + e);
+            loge("getLocalProfile:", e);
             return null;
         }
     }
@@ -290,7 +290,7 @@
         try {
             return mSession.getPeerProfile();
         } catch (RemoteException e) {
-            Log.e(TAG, "getPeerProfile(): " + e);
+            loge("getPeerProfile:", e);
             return null;
         }
     }
@@ -305,7 +305,7 @@
         try {
             return mSession.getState();
         } catch (RemoteException e) {
-            Log.e(TAG, "getState(): " + e);
+            loge("getState:", e);
             return State.NOT_DEFINED;
         }
     }
@@ -319,7 +319,7 @@
         try {
             return mSession.isInCall();
         } catch (RemoteException e) {
-            Log.e(TAG, "isInCall(): " + e);
+            loge("isInCall:", e);
             return false;
         }
     }
@@ -333,7 +333,7 @@
         try {
             return mSession.getCallId();
         } catch (RemoteException e) {
-            Log.e(TAG, "getCallId(): " + e);
+            loge("getCallId:", e);
             return null;
         }
     }
@@ -364,7 +364,7 @@
         try {
             mSession.register(duration);
         } catch (RemoteException e) {
-            Log.e(TAG, "register(): " + e);
+            loge("register:", e);
         }
     }
 
@@ -381,7 +381,7 @@
         try {
             mSession.unregister();
         } catch (RemoteException e) {
-            Log.e(TAG, "unregister(): " + e);
+            loge("unregister:", e);
         }
     }
 
@@ -402,7 +402,7 @@
         try {
             mSession.makeCall(callee, sessionDescription, timeout);
         } catch (RemoteException e) {
-            Log.e(TAG, "makeCall(): " + e);
+            loge("makeCall:", e);
         }
     }
 
@@ -420,7 +420,7 @@
         try {
             mSession.answerCall(sessionDescription, timeout);
         } catch (RemoteException e) {
-            Log.e(TAG, "answerCall(): " + e);
+            loge("answerCall:", e);
         }
     }
 
@@ -436,7 +436,7 @@
         try {
             mSession.endCall();
         } catch (RemoteException e) {
-            Log.e(TAG, "endCall(): " + e);
+            loge("endCall:", e);
         }
     }
 
@@ -453,7 +453,7 @@
         try {
             mSession.changeCall(sessionDescription, timeout);
         } catch (RemoteException e) {
-            Log.e(TAG, "changeCall(): " + e);
+            loge("changeCall:", e);
         }
     }
 
@@ -463,12 +463,14 @@
 
     private ISipSessionListener createListener() {
         return new ISipSessionListener.Stub() {
+            @Override
             public void onCalling(ISipSession session) {
                 if (mListener != null) {
                     mListener.onCalling(SipSession.this);
                 }
             }
 
+            @Override
             public void onRinging(ISipSession session, SipProfile caller,
                     String sessionDescription) {
                 if (mListener != null) {
@@ -477,12 +479,14 @@
                 }
             }
 
+            @Override
             public void onRingingBack(ISipSession session) {
                 if (mListener != null) {
                     mListener.onRingingBack(SipSession.this);
                 }
             }
 
+            @Override
             public void onCallEstablished(ISipSession session,
                     String sessionDescription) {
                 if (mListener != null) {
@@ -491,18 +495,21 @@
                 }
             }
 
+            @Override
             public void onCallEnded(ISipSession session) {
                 if (mListener != null) {
                     mListener.onCallEnded(SipSession.this);
                 }
             }
 
+            @Override
             public void onCallBusy(ISipSession session) {
                 if (mListener != null) {
                     mListener.onCallBusy(SipSession.this);
                 }
             }
 
+            @Override
             public void onCallTransferring(ISipSession session,
                     String sessionDescription) {
                 if (mListener != null) {
@@ -513,6 +520,7 @@
                 }
             }
 
+            @Override
             public void onCallChangeFailed(ISipSession session, int errorCode,
                     String message) {
                 if (mListener != null) {
@@ -521,24 +529,28 @@
                 }
             }
 
+            @Override
             public void onError(ISipSession session, int errorCode, String message) {
                 if (mListener != null) {
                     mListener.onError(SipSession.this, errorCode, message);
                 }
             }
 
+            @Override
             public void onRegistering(ISipSession session) {
                 if (mListener != null) {
                     mListener.onRegistering(SipSession.this);
                 }
             }
 
+            @Override
             public void onRegistrationDone(ISipSession session, int duration) {
                 if (mListener != null) {
                     mListener.onRegistrationDone(SipSession.this, duration);
                 }
             }
 
+            @Override
             public void onRegistrationFailed(ISipSession session, int errorCode,
                     String message) {
                 if (mListener != null) {
@@ -547,6 +559,7 @@
                 }
             }
 
+            @Override
             public void onRegistrationTimeout(ISipSession session) {
                 if (mListener != null) {
                     mListener.onRegistrationTimeout(SipSession.this);
@@ -554,4 +567,8 @@
             }
         };
     }
+
+    private void loge(String s, Throwable t) {
+        Rlog.e(TAG, s, t);
+    }
 }
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index 113f007..c708be8 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -24,7 +24,7 @@
 import gov.nist.javax.sip.header.extensions.ReplacesHeader;
 
 import android.net.sip.SipProfile;
-import android.util.Log;
+import android.telephony.Rlog;
 
 import java.text.ParseException;
 import java.util.ArrayList;
@@ -46,9 +46,7 @@
 import javax.sip.SipProvider;
 import javax.sip.SipStack;
 import javax.sip.Transaction;
-import javax.sip.TransactionAlreadyExistsException;
 import javax.sip.TransactionTerminatedEvent;
-import javax.sip.TransactionUnavailableException;
 import javax.sip.TransactionState;
 import javax.sip.address.Address;
 import javax.sip.address.AddressFactory;
@@ -73,8 +71,8 @@
  */
 class SipHelper {
     private static final String TAG = SipHelper.class.getSimpleName();
-    private static final boolean DEBUG = false;
-    private static final boolean DEBUG_PING = false;
+    private static final boolean DBG = false;
+    private static final boolean DBG_PING = false;
 
     private SipStack mSipStack;
     private SipProvider mSipProvider;
@@ -262,7 +260,7 @@
         ClientTransaction tid = responseEvent.getClientTransaction();
         ClientTransaction ct = authenticationHelper.handleChallenge(
                 responseEvent.getResponse(), tid, mSipProvider, 5);
-        if (DEBUG) Log.d(TAG, "send request with challenge response: "
+        if (DBG) log("send request with challenge response: "
                 + ct.getRequest());
         ct.sendRequest();
         return ct;
@@ -301,7 +299,7 @@
                             "application", "sdp"));
             ClientTransaction clientTransaction =
                     mSipProvider.getNewClientTransaction(request);
-            if (DEBUG) Log.d(TAG, "send INVITE: " + request);
+            if (DBG) log("send INVITE: " + request);
             clientTransaction.sendRequest();
             return clientTransaction;
         } catch (ParseException e) {
@@ -326,7 +324,7 @@
 
             ClientTransaction clientTransaction =
                     mSipProvider.getNewClientTransaction(request);
-            if (DEBUG) Log.d(TAG, "send RE-INVITE: " + request);
+            if (DBG) log("send RE-INVITE: " + request);
             dialog.sendRequest(clientTransaction);
             return clientTransaction;
         } catch (ParseException e) {
@@ -360,7 +358,7 @@
             ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
             toHeader.setTag(tag);
             response.addHeader(toHeader);
-            if (DEBUG) Log.d(TAG, "send RINGING: " + response);
+            if (DBG) log("send RINGING: " + response);
             transaction.sendResponse(response);
             return transaction;
         } catch (ParseException e) {
@@ -390,7 +388,7 @@
             }
 
             if (inviteTransaction.getState() != TransactionState.COMPLETED) {
-                if (DEBUG) Log.d(TAG, "send OK: " + response);
+                if (DBG) log("send OK: " + response);
                 inviteTransaction.sendResponse(response);
             }
 
@@ -412,7 +410,7 @@
             }
 
             if (inviteTransaction.getState() != TransactionState.COMPLETED) {
-                if (DEBUG) Log.d(TAG, "send BUSY HERE: " + response);
+                if (DBG) log("send BUSY HERE: " + response);
                 inviteTransaction.sendResponse(response);
             }
         } catch (ParseException e) {
@@ -429,20 +427,20 @@
         long cseq = ((CSeqHeader) response.getHeader(CSeqHeader.NAME))
                 .getSeqNumber();
         Request ack = dialog.createAck(cseq);
-        if (DEBUG) Log.d(TAG, "send ACK: " + ack);
+        if (DBG) log("send ACK: " + ack);
         dialog.sendAck(ack);
     }
 
     public void sendBye(Dialog dialog) throws SipException {
         Request byeRequest = dialog.createRequest(Request.BYE);
-        if (DEBUG) Log.d(TAG, "send BYE: " + byeRequest);
+        if (DBG) log("send BYE: " + byeRequest);
         dialog.sendRequest(mSipProvider.getNewClientTransaction(byeRequest));
     }
 
     public void sendCancel(ClientTransaction inviteTransaction)
             throws SipException {
         Request cancelRequest = inviteTransaction.createCancel();
-        if (DEBUG) Log.d(TAG, "send CANCEL: " + cancelRequest);
+        if (DBG) log("send CANCEL: " + cancelRequest);
         mSipProvider.getNewClientTransaction(cancelRequest).sendRequest();
     }
 
@@ -452,9 +450,9 @@
             Request request = event.getRequest();
             Response response = mMessageFactory.createResponse(
                     responseCode, request);
-            if (DEBUG && (!Request.OPTIONS.equals(request.getMethod())
-                    || DEBUG_PING)) {
-                Log.d(TAG, "send response: " + response);
+            if (DBG && (!Request.OPTIONS.equals(request.getMethod())
+                    || DBG_PING)) {
+                log("send response: " + response);
             }
             getServerTransaction(event).sendResponse(response);
         } catch (ParseException e) {
@@ -474,7 +472,7 @@
                             "message", "sipfrag"));
             request.addHeader(mHeaderFactory.createEventHeader(
                     ReferencesHeader.REFER));
-            if (DEBUG) Log.d(TAG, "send NOTIFY: " + request);
+            if (DBG) log("send NOTIFY: " + request);
             dialog.sendRequest(mSipProvider.getNewClientTransaction(request));
         } catch (ParseException e) {
             throw new SipException("sendReferNotify()", e);
@@ -486,7 +484,7 @@
         try {
             Response response = mMessageFactory.createResponse(
                     Response.REQUEST_TERMINATED, inviteRequest);
-            if (DEBUG) Log.d(TAG, "send response: " + response);
+            if (DBG) log("send response: " + response);
             inviteTransaction.sendResponse(response);
         } catch (ParseException e) {
             throw new SipException("sendInviteRequestTerminated()", e);
@@ -532,4 +530,8 @@
     private static String getCallId(Dialog dialog) {
         return dialog.getCallId().getCallId();
     }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
+    }
 }
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index a477fd1..80fe68c 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -16,7 +16,6 @@
 
 package com.android.server.sip;
 
-import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -44,22 +43,15 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.Log;
+import android.telephony.Rlog;
 
 import java.io.IOException;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Comparator;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.TreeSet;
 import java.util.concurrent.Executor;
 import javax.sip.SipException;
 
@@ -68,7 +60,7 @@
  */
 public final class SipService extends ISipService.Stub {
     static final String TAG = "SipService";
-    static final boolean DEBUG = false;
+    static final boolean DBG = true;
     private static final int EXPIRY_TIME = 3600;
     private static final int SHORT_EXPIRY_TIME = 10;
     private static final int MIN_EXPIRY_TIME = 60;
@@ -82,7 +74,7 @@
     private WifiManager.WifiLock mWifiLock;
     private boolean mSipOnWifiOnly;
 
-    private IntervalMeasurementProcess mIntervalMeasurementProcess;
+    private SipKeepAliveProcessCallback mSipKeepAliveProcessCallback;
 
     private MyExecutor mExecutor = new MyExecutor();
 
@@ -107,12 +99,12 @@
         if (SipManager.isApiSupported(context)) {
             ServiceManager.addService("sip", new SipService(context));
             context.sendBroadcast(new Intent(SipManager.ACTION_SIP_SERVICE_UP));
-            if (DEBUG) Log.d(TAG, "SIP service started");
+            if (DBG) slog("start:");
         }
     }
 
     private SipService(Context context) {
-        if (DEBUG) Log.d(TAG, " service started!");
+        if (DBG) log("SipService: started!");
         mContext = context;
         mConnectivityReceiver = new ConnectivityReceiver();
 
@@ -128,6 +120,7 @@
         mTimer = new SipWakeupTimer(context, mExecutor);
     }
 
+    @Override
     public synchronized SipProfile[] getListOfProfiles() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
@@ -141,6 +134,7 @@
         return profiles.toArray(new SipProfile[profiles.size()]);
     }
 
+    @Override
     public synchronized void open(SipProfile localProfile) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
@@ -148,11 +142,12 @@
         try {
             createGroup(localProfile);
         } catch (SipException e) {
-            Log.e(TAG, "openToMakeCalls()", e);
+            loge("openToMakeCalls()", e);
             // TODO: how to send the exception back
         }
     }
 
+    @Override
     public synchronized void open3(SipProfile localProfile,
             PendingIntent incomingCallPendingIntent,
             ISipSessionListener listener) {
@@ -160,11 +155,11 @@
                 android.Manifest.permission.USE_SIP, null);
         localProfile.setCallingUid(Binder.getCallingUid());
         if (incomingCallPendingIntent == null) {
-            Log.w(TAG, "incomingCallPendingIntent cannot be null; "
+            if (DBG) log("open3: incomingCallPendingIntent cannot be null; "
                     + "the profile is not opened");
             return;
         }
-        if (DEBUG) Log.d(TAG, "open3: " + localProfile.getUriString() + ": "
+        if (DBG) log("open3: " + localProfile.getUriString() + ": "
                 + incomingCallPendingIntent + ": " + listener);
         try {
             SipSessionGroupExt group = createGroup(localProfile,
@@ -174,7 +169,7 @@
                 updateWakeLocks();
             }
         } catch (SipException e) {
-            Log.e(TAG, "openToReceiveCalls()", e);
+            loge("open3:", e);
             // TODO: how to send the exception back
         }
     }
@@ -192,13 +187,14 @@
         return (Binder.getCallingUid() == Process.PHONE_UID);
     }
 
+    @Override
     public synchronized void close(String localProfileUri) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
         SipSessionGroupExt group = mSipGroups.get(localProfileUri);
         if (group == null) return;
         if (!isCallerCreatorOrRadio(group)) {
-            Log.w(TAG, "only creator or radio can close this profile");
+            if (DBG) log("only creator or radio can close this profile");
             return;
         }
 
@@ -209,6 +205,7 @@
         updateWakeLocks();
     }
 
+    @Override
     public synchronized boolean isOpened(String localProfileUri) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
@@ -217,11 +214,12 @@
         if (isCallerCreatorOrRadio(group)) {
             return true;
         } else {
-            Log.w(TAG, "only creator or radio can query on the profile");
+            if (DBG) log("only creator or radio can query on the profile");
             return false;
         }
     }
 
+    @Override
     public synchronized boolean isRegistered(String localProfileUri) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
@@ -230,11 +228,12 @@
         if (isCallerCreatorOrRadio(group)) {
             return group.isRegistered();
         } else {
-            Log.w(TAG, "only creator or radio can query on the profile");
+            if (DBG) log("only creator or radio can query on the profile");
             return false;
         }
     }
 
+    @Override
     public synchronized void setRegistrationListener(String localProfileUri,
             ISipSessionListener listener) {
         mContext.enforceCallingOrSelfPermission(
@@ -244,25 +243,31 @@
         if (isCallerCreator(group)) {
             group.setListener(listener);
         } else {
-            Log.w(TAG, "only creator can set listener on the profile");
+            if (DBG) log("only creator can set listener on the profile");
         }
     }
 
+    @Override
     public synchronized ISipSession createSession(SipProfile localProfile,
             ISipSessionListener listener) {
+        if (DBG) log("createSession: profile" + localProfile);
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
         localProfile.setCallingUid(Binder.getCallingUid());
-        if (mNetworkType == -1) return null;
+        if (mNetworkType == -1) {
+            if (DBG) log("createSession: mNetworkType==-1 ret=null");
+            return null;
+        }
         try {
             SipSessionGroupExt group = createGroup(localProfile);
             return group.createSession(listener);
         } catch (SipException e) {
-            if (DEBUG) Log.d(TAG, "createSession()", e);
+            if (DBG) loge("createSession;", e);
             return null;
         }
     }
 
+    @Override
     public synchronized ISipSession getPendingSession(String callId) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
@@ -276,7 +281,7 @@
             s.connect(InetAddress.getByName("192.168.1.1"), 80);
             return s.getLocalAddress().getHostAddress();
         } catch (IOException e) {
-            if (DEBUG) Log.d(TAG, "determineLocalIp()", e);
+            if (DBG) loge("determineLocalIp()", e);
             // dont do anything; there should be a connectivity change going
             return null;
         }
@@ -317,7 +322,7 @@
     }
 
     private void notifyProfileAdded(SipProfile localProfile) {
-        if (DEBUG) Log.d(TAG, "notify: profile added: " + localProfile);
+        if (DBG) log("notify: profile added: " + localProfile);
         Intent intent = new Intent(SipManager.ACTION_SIP_ADD_PHONE);
         intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString());
         mContext.sendBroadcast(intent);
@@ -327,7 +332,7 @@
     }
 
     private void notifyProfileRemoved(SipProfile localProfile) {
-        if (DEBUG) Log.d(TAG, "notify: profile removed: " + localProfile);
+        if (DBG) log("notify: profile removed: " + localProfile);
         Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PHONE);
         intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString());
         mContext.sendBroadcast(intent);
@@ -337,9 +342,9 @@
     }
 
     private void stopPortMappingMeasurement() {
-        if (mIntervalMeasurementProcess != null) {
-            mIntervalMeasurementProcess.stop();
-            mIntervalMeasurementProcess = null;
+        if (mSipKeepAliveProcessCallback != null) {
+            mSipKeepAliveProcessCallback.stop();
+            mSipKeepAliveProcessCallback = null;
         }
     }
 
@@ -351,10 +356,10 @@
 
     private void startPortMappingLifetimeMeasurement(
             SipProfile localProfile, int maxInterval) {
-        if ((mIntervalMeasurementProcess == null)
+        if ((mSipKeepAliveProcessCallback == null)
                 && (mKeepAliveInterval == -1)
                 && isBehindNAT(mLocalIp)) {
-            Log.d(TAG, "start NAT port mapping timeout measurement on "
+            if (DBG) log("startPortMappingLifetimeMeasurement: profile="
                     + localProfile.getUriString());
 
             int minInterval = mLastGoodKeepAliveInterval;
@@ -363,11 +368,11 @@
                 // to the default min
                 minInterval = mLastGoodKeepAliveInterval
                         = DEFAULT_KEEPALIVE_INTERVAL;
-                Log.d(TAG, "  reset min interval to " + minInterval);
+                log("  reset min interval to " + minInterval);
             }
-            mIntervalMeasurementProcess = new IntervalMeasurementProcess(
+            mSipKeepAliveProcessCallback = new SipKeepAliveProcessCallback(
                     localProfile, minInterval, maxInterval);
-            mIntervalMeasurementProcess.start();
+            mSipKeepAliveProcessCallback.start();
         }
     }
 
@@ -382,10 +387,10 @@
         try {
             cleanUpPendingSessions();
             mPendingSessions.put(session.getCallId(), session);
-            if (DEBUG) Log.d(TAG, "#pending sess=" + mPendingSessions.size());
+            if (DBG) log("#pending sess=" + mPendingSessions.size());
         } catch (RemoteException e) {
             // should not happen with a local call
-            Log.e(TAG, "addPendingSession()", e);
+            loge("addPendingSession()", e);
         }
     }
 
@@ -405,7 +410,7 @@
         String callId = ringingSession.getCallId();
         for (SipSessionGroupExt group : mSipGroups.values()) {
             if ((group != ringingGroup) && group.containsSession(callId)) {
-                if (DEBUG) Log.d(TAG, "call self: "
+                if (DBG) log("call self: "
                         + ringingSession.getLocalProfile().getUriString()
                         + " -> " + group.getLocalProfile().getUriString());
                 return true;
@@ -428,31 +433,36 @@
 
     private boolean isBehindNAT(String address) {
         try {
+            // TODO: How is isBehindNAT used and why these constanst address:
+            //       10.x.x.x | 192.168.x.x | 172.16.x.x .. 172.19.x.x
             byte[] d = InetAddress.getByName(address).getAddress();
             if ((d[0] == 10) ||
-                    (((0x000000FF & ((int)d[0])) == 172) &&
-                    ((0x000000F0 & ((int)d[1])) == 16)) ||
-                    (((0x000000FF & ((int)d[0])) == 192) &&
-                    ((0x000000FF & ((int)d[1])) == 168))) {
+                    (((0x000000FF & d[0]) == 172) &&
+                    ((0x000000F0 & d[1]) == 16)) ||
+                    (((0x000000FF & d[0]) == 192) &&
+                    ((0x000000FF & d[1]) == 168))) {
                 return true;
             }
         } catch (UnknownHostException e) {
-            Log.e(TAG, "isBehindAT()" + address, e);
+            loge("isBehindAT()" + address, e);
         }
         return false;
     }
 
     private class SipSessionGroupExt extends SipSessionAdapter {
+        private static final String SSGE_TAG = "SipSessionGroupExt";
+        private static final boolean SSGE_DBG = true;
         private SipSessionGroup mSipGroup;
         private PendingIntent mIncomingCallPendingIntent;
         private boolean mOpenedToReceiveCalls;
 
-        private AutoRegistrationProcess mAutoRegistration =
-                new AutoRegistrationProcess();
+        private SipAutoReg mAutoRegistration =
+                new SipAutoReg();
 
         public SipSessionGroupExt(SipProfile localProfile,
                 PendingIntent incomingCallPendingIntent,
                 ISipSessionListener listener) throws SipException {
+            if (SSGE_DBG) log("SipSessionGroupExt: profile=" + localProfile);
             mSipGroup = new SipSessionGroup(duplicate(localProfile),
                     localProfile.getPassword(), mTimer, mMyWakeLock);
             mIncomingCallPendingIntent = incomingCallPendingIntent;
@@ -481,7 +491,7 @@
             try {
                 return new SipProfile.Builder(p).setPassword("*").build();
             } catch (Exception e) {
-                Log.wtf(TAG, "duplicate()", e);
+                loge("duplicate()", e);
                 throw new RuntimeException("duplicate profile", e);
             }
         }
@@ -500,20 +510,21 @@
                 mSipGroup.openToReceiveCalls(this);
                 mAutoRegistration.start(mSipGroup);
             }
-            if (DEBUG) Log.d(TAG, "  openToReceiveCalls: " + getUri() + ": "
+            if (SSGE_DBG) log("openToReceiveCalls: " + getUri() + ": "
                     + mIncomingCallPendingIntent);
         }
 
         public void onConnectivityChanged(boolean connected)
                 throws SipException {
+            if (SSGE_DBG) {
+                log("onConnectivityChanged: connected=" + connected + " uri="
+                    + getUri() + ": " + mIncomingCallPendingIntent);
+            }
             mSipGroup.onConnectivityChanged();
             if (connected) {
                 mSipGroup.reset();
                 if (mOpenedToReceiveCalls) openToReceiveCalls();
             } else {
-                // close mSipGroup but remember mOpenedToReceiveCalls
-                if (DEBUG) Log.d(TAG, "  close auto reg temporarily: "
-                        + getUri() + ": " + mIncomingCallPendingIntent);
                 mSipGroup.close();
                 mAutoRegistration.stop();
             }
@@ -523,23 +534,23 @@
             mOpenedToReceiveCalls = false;
             mSipGroup.close();
             mAutoRegistration.stop();
-            if (DEBUG) Log.d(TAG, "   close: " + getUri() + ": "
-                    + mIncomingCallPendingIntent);
+            if (SSGE_DBG) log("close: " + getUri() + ": " + mIncomingCallPendingIntent);
         }
 
         public ISipSession createSession(ISipSessionListener listener) {
+            if (SSGE_DBG) log("createSession");
             return mSipGroup.createSession(listener);
         }
 
         @Override
         public void onRinging(ISipSession s, SipProfile caller,
                 String sessionDescription) {
-            if (DEBUG) Log.d(TAG, "<<<<< onRinging()");
             SipSessionGroup.SipSessionImpl session =
                     (SipSessionGroup.SipSessionImpl) s;
             synchronized (SipService.this) {
                 try {
                     if (!isRegistered() || callingSelf(this, session)) {
+                        if (SSGE_DBG) log("onRinging: end notReg or self");
                         session.endCall();
                         return;
                     }
@@ -548,13 +559,13 @@
                     addPendingSession(session);
                     Intent intent = SipManager.createIncomingCallBroadcast(
                             session.getCallId(), sessionDescription);
-                    if (DEBUG) Log.d(TAG, " ringing~~ " + getUri() + ": "
+                    if (SSGE_DBG) log("onRinging: uri=" + getUri() + ": "
                             + caller.getUri() + ": " + session.getCallId()
                             + " " + mIncomingCallPendingIntent);
                     mIncomingCallPendingIntent.send(mContext,
                             SipManager.INCOMING_CALL_RESULT_CODE, intent);
                 } catch (PendingIntent.CanceledException e) {
-                    Log.w(TAG, "pendingIntent is canceled, drop incoming call");
+                    loge("onRinging: pendingIntent is canceled, drop incoming call", e);
                     session.endCall();
                 }
             }
@@ -563,7 +574,7 @@
         @Override
         public void onError(ISipSession session, int errorCode,
                 String message) {
-            if (DEBUG) Log.d(TAG, "sip session error: "
+            if (SSGE_DBG) log("onError: errorCode=" + errorCode + " desc="
                     + SipErrorCode.toString(errorCode) + ": " + message);
         }
 
@@ -578,14 +589,23 @@
         private String getUri() {
             return mSipGroup.getLocalProfileUri();
         }
+
+        private void log(String s) {
+            Rlog.d(SSGE_TAG, s);
+        }
+
+        private void loge(String s, Throwable t) {
+            Rlog.e(SSGE_TAG, s, t);
+        }
+
     }
 
-    private class IntervalMeasurementProcess implements Runnable,
+    private class SipKeepAliveProcessCallback implements Runnable,
             SipSessionGroup.KeepAliveProcessCallback {
-        private static final String TAG = "SipKeepAliveInterval";
+        private static final String SKAI_TAG = "SipKeepAliveProcessCallback";
+        private static final boolean SKAI_DBG = true;
         private static final int MIN_INTERVAL = 5; // in seconds
         private static final int PASS_THRESHOLD = 10;
-        private static final int MAX_RETRY_COUNT = 5;
         private static final int NAT_MEASUREMENT_RETRY_INTERVAL = 120; // in seconds
         private SipProfile mLocalProfile;
         private SipSessionGroupExt mGroup;
@@ -595,7 +615,7 @@
         private int mInterval;
         private int mPassCount;
 
-        public IntervalMeasurementProcess(SipProfile localProfile,
+        public SipKeepAliveProcessCallback(SipProfile localProfile,
                 int minInterval, int maxInterval) {
             mMaxInterval = maxInterval;
             mMinInterval = minInterval;
@@ -613,13 +633,13 @@
 
                 // Don't start measurement if the interval is too small
                 if (mInterval < DEFAULT_KEEPALIVE_INTERVAL || checkTermination()) {
-                    Log.w(TAG, "measurement aborted; interval=[" +
+                    if (SKAI_DBG) log("start: measurement aborted; interval=[" +
                             mMinInterval + "," + mMaxInterval + "]");
                     return;
                 }
 
                 try {
-                    Log.d(TAG, "start measurement w interval=" + mInterval);
+                    if (SKAI_DBG) log("start: interval=" + mInterval);
 
                     mGroup = new SipSessionGroupExt(mLocalProfile, null, null);
                     // TODO: remove this line once SipWakeupTimer can better handle
@@ -646,6 +666,7 @@
                     mGroup = null;
                 }
                 mTimer.cancel(this);
+                if (SKAI_DBG) log("stop");
             }
         }
 
@@ -654,13 +675,13 @@
                 // Return immediately if the measurement process is stopped
                 if (mSession == null) return;
 
-                Log.d(TAG, "restart measurement w interval=" + mInterval);
+                if (SKAI_DBG) log("restart: interval=" + mInterval);
                 try {
                     mSession.stopKeepAliveProcess();
                     mPassCount = 0;
                     mSession.startKeepAliveProcess(mInterval, this);
                 } catch (SipException e) {
-                    Log.e(TAG, "restart()", e);
+                    loge("restart", e);
                 }
             }
         }
@@ -681,8 +702,8 @@
                         mLastGoodKeepAliveInterval = mKeepAliveInterval;
                     }
                     mKeepAliveInterval = mMinInterval = mInterval;
-                    if (DEBUG) {
-                        Log.d(TAG, "measured good keepalive interval: "
+                    if (SKAI_DBG) {
+                        log("onResponse: portChanged=" + portChanged + " mKeepAliveInterval="
                                 + mKeepAliveInterval);
                     }
                     onKeepAliveIntervalChanged();
@@ -698,16 +719,16 @@
                     // measurement with min interval=DEFAULT_KEEPALIVE_INTERVAL
                     // will be conducted.
                     mKeepAliveInterval = mMinInterval;
-                    if (DEBUG) {
-                        Log.d(TAG, "measured keepalive interval: "
+                    if (SKAI_DBG) {
+                        log("onResponse: checkTermination mKeepAliveInterval="
                                 + mKeepAliveInterval);
                     }
                 } else {
                     // calculate the new interval and continue.
                     mInterval = (mMaxInterval + mMinInterval) / 2;
-                    if (DEBUG) {
-                        Log.d(TAG, "current interval: " + mKeepAliveInterval
-                                + ", test new interval: " + mInterval);
+                    if (SKAI_DBG) {
+                        log("onResponse: mKeepAliveInterval=" + mKeepAliveInterval
+                                + ", new mInterval=" + mInterval);
                     }
                     restart();
                 }
@@ -717,7 +738,7 @@
         // SipSessionGroup.KeepAliveProcessCallback
         @Override
         public void onError(int errorCode, String description) {
-            Log.w(TAG, "interval measurement error: " + description);
+            if (SKAI_DBG) loge("onError: errorCode=" + errorCode + " desc=" + description);
             restartLater();
         }
 
@@ -735,12 +756,25 @@
                 mTimer.set(interval * 1000, this);
             }
         }
+
+        private void log(String s) {
+            Rlog.d(SKAI_TAG, s);
+        }
+
+        private void loge(String s) {
+            Rlog.d(SKAI_TAG, s);
+        }
+
+        private void loge(String s, Throwable t) {
+            Rlog.d(SKAI_TAG, s, t);
+        }
     }
 
-    private class AutoRegistrationProcess extends SipSessionAdapter
+    private class SipAutoReg extends SipSessionAdapter
             implements Runnable, SipSessionGroup.KeepAliveProcessCallback {
+        private String SAR_TAG;
+        private static final boolean SAR_DBG = true;
         private static final int MIN_KEEPALIVE_SUCCESS_COUNT = 10;
-        private String TAG = "SipAutoReg";
 
         private SipSessionGroup.SipSessionImpl mSession;
         private SipSessionGroup.SipSessionImpl mKeepAliveSession;
@@ -754,10 +788,6 @@
 
         private int mKeepAliveSuccessCount = 0;
 
-        private String getAction() {
-            return toString();
-        }
-
         public void start(SipSessionGroup group) {
             if (!mRunning) {
                 mRunning = true;
@@ -772,12 +802,13 @@
                 // in registration to avoid adding duplicate entries to server
                 mMyWakeLock.acquire(mSession);
                 mSession.unregister();
-                TAG = "SipAutoReg:" + mSession.getLocalProfile().getUriString();
+                SAR_TAG = "SipAutoReg:" + mSession.getLocalProfile().getUriString();
+                if (SAR_DBG) log("start: group=" + group);
             }
         }
 
         private void startKeepAliveProcess(int interval) {
-            if (DEBUG) Log.d(TAG, "start keepalive w interval=" + interval);
+            if (SAR_DBG) log("startKeepAliveProcess: interval=" + interval);
             if (mKeepAliveSession == null) {
                 mKeepAliveSession = mSession.duplicate();
             } else {
@@ -786,8 +817,7 @@
             try {
                 mKeepAliveSession.startKeepAliveProcess(interval, this);
             } catch (SipException e) {
-                Log.e(TAG, "failed to start keepalive w interval=" + interval,
-                        e);
+                loge("startKeepAliveProcess: interval=" + interval, e);
             }
         }
 
@@ -806,17 +836,19 @@
                 if (portChanged) {
                     int interval = getKeepAliveInterval();
                     if (mKeepAliveSuccessCount < MIN_KEEPALIVE_SUCCESS_COUNT) {
-                        Log.i(TAG, "keepalive doesn't work with interval "
-                                + interval + ", past success count="
-                                + mKeepAliveSuccessCount);
+                        if (SAR_DBG) {
+                            log("onResponse: keepalive doesn't work with interval "
+                                    + interval + ", past success count="
+                                    + mKeepAliveSuccessCount);
+                        }
                         if (interval > DEFAULT_KEEPALIVE_INTERVAL) {
                             restartPortMappingLifetimeMeasurement(
                                     mSession.getLocalProfile(), interval);
                             mKeepAliveSuccessCount = 0;
                         }
                     } else {
-                        if (DEBUG) {
-                            Log.i(TAG, "keep keepalive going with interval "
+                        if (SAR_DBG) {
+                            log("keep keepalive going with interval "
                                     + interval + ", past success count="
                                     + mKeepAliveSuccessCount);
                         }
@@ -847,8 +879,8 @@
         // SipSessionGroup.KeepAliveProcessCallback
         @Override
         public void onError(int errorCode, String description) {
-            if (DEBUG) {
-                Log.e(TAG, "keepalive error: " + description);
+            if (SAR_DBG) {
+                loge("onError: errorCode=" + errorCode + " desc=" + description);
             }
             onResponse(true); // re-register immediately
         }
@@ -872,8 +904,8 @@
         public void onKeepAliveIntervalChanged() {
             if (mKeepAliveSession != null) {
                 int newInterval = getKeepAliveInterval();
-                if (DEBUG) {
-                    Log.v(TAG, "restart keepalive w interval=" + newInterval);
+                if (SAR_DBG) {
+                    log("onKeepAliveIntervalChanged: interval=" + newInterval);
                 }
                 mKeepAliveSuccessCount = 0;
                 startKeepAliveProcess(newInterval);
@@ -916,7 +948,7 @@
                                 String.valueOf(state));
                     }
                 } catch (Throwable t) {
-                    Log.w(TAG, "setListener(): " + t);
+                    loge("setListener: ", t);
                 }
             }
         }
@@ -933,7 +965,7 @@
 
                 mErrorCode = SipErrorCode.NO_ERROR;
                 mErrorMessage = null;
-                if (DEBUG) Log.d(TAG, "registering");
+                if (SAR_DBG) log("run: registering");
                 if (mNetworkType != -1) {
                     mMyWakeLock.acquire(mSession);
                     mSession.register(EXPIRY_TIME);
@@ -942,7 +974,7 @@
         }
 
         private void restart(int duration) {
-            Log.d(TAG, "Refresh registration " + duration + "s later.");
+            if (SAR_DBG) log("restart: duration=" + duration + "s later.");
             mTimer.cancel(this);
             mTimer.set(duration * 1000, this);
         }
@@ -959,7 +991,7 @@
 
         @Override
         public void onRegistering(ISipSession session) {
-            if (DEBUG) Log.d(TAG, "onRegistering(): " + session);
+            if (SAR_DBG) log("onRegistering: " + session);
             synchronized (SipService.this) {
                 if (notCurrentSession(session)) return;
 
@@ -979,7 +1011,7 @@
 
         @Override
         public void onRegistrationDone(ISipSession session, int duration) {
-            if (DEBUG) Log.d(TAG, "onRegistrationDone(): " + session);
+            if (SAR_DBG) log("onRegistrationDone: " + session);
             synchronized (SipService.this) {
                 if (notCurrentSession(session)) return;
 
@@ -1008,7 +1040,7 @@
                 } else {
                     mRegistered = false;
                     mExpiryTime = -1L;
-                    if (DEBUG) Log.d(TAG, "Refresh registration immediately");
+                    if (SAR_DBG) log("Refresh registration immediately");
                     run();
                 }
             }
@@ -1017,7 +1049,7 @@
         @Override
         public void onRegistrationFailed(ISipSession session, int errorCode,
                 String message) {
-            if (DEBUG) Log.d(TAG, "onRegistrationFailed(): " + session + ": "
+            if (SAR_DBG) log("onRegistrationFailed: " + session + ": "
                     + SipErrorCode.toString(errorCode) + ": " + message);
             synchronized (SipService.this) {
                 if (notCurrentSession(session)) return;
@@ -1025,7 +1057,7 @@
                 switch (errorCode) {
                     case SipErrorCode.INVALID_CREDENTIALS:
                     case SipErrorCode.SERVER_UNREACHABLE:
-                        if (DEBUG) Log.d(TAG, "   pause auto-registration");
+                        if (SAR_DBG) log("   pause auto-registration");
                         stop();
                         break;
                     default:
@@ -1041,7 +1073,7 @@
 
         @Override
         public void onRegistrationTimeout(ISipSession session) {
-            if (DEBUG) Log.d(TAG, "onRegistrationTimeout(): " + session);
+            if (SAR_DBG) log("onRegistrationTimeout: " + session);
             synchronized (SipService.this) {
                 if (notCurrentSession(session)) return;
 
@@ -1053,9 +1085,22 @@
         }
 
         private void restartLater() {
+            if (SAR_DBG) loge("restartLater");
             mRegistered = false;
             restart(backoffDuration());
         }
+
+        private void log(String s) {
+            Rlog.d(SAR_TAG, s);
+        }
+
+        private void loge(String s) {
+            Rlog.e(SAR_TAG, s);
+        }
+
+        private void loge(String s, Throwable e) {
+            Rlog.e(SAR_TAG, s, e);
+        }
     }
 
     private class ConnectivityReceiver extends BroadcastReceiver {
@@ -1068,6 +1113,7 @@
 
                 // Run the handler in MyExecutor to be protected by wake lock
                 mExecutor.execute(new Runnable() {
+                    @Override
                     public void run() {
                         onConnectivityChanged(info);
                     }
@@ -1079,12 +1125,12 @@
     private void registerReceivers() {
         mContext.registerReceiver(mConnectivityReceiver,
                 new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
-        if (DEBUG) Log.d(TAG, " +++ register receivers");
+        if (DBG) log("registerReceivers:");
     }
 
     private void unregisterReceivers() {
         mContext.unregisterReceiver(mConnectivityReceiver);
-        if (DEBUG) Log.d(TAG, " --- unregister receivers");
+        if (DBG) log("unregisterReceivers:");
 
         // Reset variables maintained by ConnectivityReceiver.
         mWifiLock.release();
@@ -1131,10 +1177,11 @@
 
         // Ignore the event if the current active network is not changed.
         if (mNetworkType == networkType) {
+            // TODO: Maybe we need to send seq/generation number
             return;
         }
-        if (DEBUG) {
-            Log.d(TAG, "onConnectivityChanged(): " + mNetworkType +
+        if (DBG) {
+            log("onConnectivityChanged: " + mNetworkType +
                     " -> " + networkType);
         }
 
@@ -1158,7 +1205,7 @@
             }
             updateWakeLocks();
         } catch (SipException e) {
-            Log.e(TAG, "onConnectivityChanged()", e);
+            loge("onConnectivityChanged()", e);
         }
     }
 
@@ -1186,7 +1233,7 @@
             if (msg.obj instanceof Runnable) {
                 executeInternal((Runnable) msg.obj);
             } else {
-                Log.w(TAG, "can't handle msg: " + msg);
+                if (DBG) log("handleMessage: not Runnable ignore msg=" + msg);
             }
         }
 
@@ -1194,10 +1241,22 @@
             try {
                 task.run();
             } catch (Throwable t) {
-                Log.e(TAG, "run task: " + task, t);
+                loge("run task: " + task, t);
             } finally {
                 mMyWakeLock.release(task);
             }
         }
     }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
+    }
+
+    private static void slog(String s) {
+        Rlog.d(TAG, s);
+    }
+
+    private void loge(String s, Throwable e) {
+        Rlog.e(TAG, s, e);
+    }
 }
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 6acd456..e820f35 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -35,7 +35,7 @@
 import android.net.sip.SipSession;
 import android.net.sip.SipSessionAdapter;
 import android.text.TextUtils;
-import android.util.Log;
+import android.telephony.Rlog;
 
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
@@ -43,7 +43,6 @@
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.text.ParseException;
-import java.util.Collection;
 import java.util.EventObject;
 import java.util.HashMap;
 import java.util.Map;
@@ -53,7 +52,6 @@
 import javax.sip.Dialog;
 import javax.sip.DialogTerminatedEvent;
 import javax.sip.IOExceptionEvent;
-import javax.sip.ListeningPoint;
 import javax.sip.ObjectInUseException;
 import javax.sip.RequestEvent;
 import javax.sip.ResponseEvent;
@@ -65,9 +63,7 @@
 import javax.sip.SipStack;
 import javax.sip.TimeoutEvent;
 import javax.sip.Transaction;
-import javax.sip.TransactionState;
 import javax.sip.TransactionTerminatedEvent;
-import javax.sip.TransactionUnavailableException;
 import javax.sip.address.Address;
 import javax.sip.address.SipURI;
 import javax.sip.header.CSeqHeader;
@@ -88,8 +84,8 @@
  */
 class SipSessionGroup implements SipListener {
     private static final String TAG = "SipSession";
-    private static final boolean DEBUG = false;
-    private static final boolean DEBUG_PING = false;
+    private static final boolean DBG = false;
+    private static final boolean DBG_PING = false;
     private static final String ANONYMOUS = "anonymous";
     // Limit the size of thread pool to 1 for the order issue when the phone is
     // waken up from sleep and there are many packets to be processed in the SIP
@@ -105,9 +101,6 @@
 
     private static final EventObject DEREGISTER = new EventObject("Deregister");
     private static final EventObject END_CALL = new EventObject("End call");
-    private static final EventObject HOLD_CALL = new EventObject("Hold call");
-    private static final EventObject CONTINUE_CALL
-            = new EventObject("Continue call");
 
     private final SipProfile mLocalProfile;
     private final String mPassword;
@@ -133,7 +126,7 @@
     /**
      * @param profile the local profile with password crossed out
      * @param password the password of the profile
-     * @throws IOException if cannot assign requested address
+     * @throws SipException if cannot assign requested address
      */
     public SipSessionGroup(SipProfile profile, String password,
             SipWakeupTimer timer, SipWakeLock wakeLock) throws SipException {
@@ -206,7 +199,7 @@
             throw new SipException("failed to initialize SIP stack", e);
         }
 
-        Log.d(TAG, " start stack for " + mLocalProfile.getUriString());
+        if (DBG) log("reset: start stack for " + mLocalProfile.getUriString());
         mSipStack.start();
     }
 
@@ -224,8 +217,8 @@
     }
 
     synchronized void resetExternalAddress() {
-        if (DEBUG) {
-            Log.d(TAG, " reset external addr on " + mSipStack);
+        if (DBG) {
+            log("resetExternalAddress: " + mSipStack);
         }
         mExternalIp = null;
         mExternalPort = 0;
@@ -244,7 +237,7 @@
     }
 
     public synchronized void close() {
-        Log.d(TAG, " close stack for " + mLocalProfile.getUriString());
+        if (DBG) log("close: " + mLocalProfile.getUriString());
         onConnectivityChanged();
         mSessionMap.clear();
         closeToNotReceiveCalls();
@@ -285,10 +278,10 @@
         String key = SipHelper.getCallId(event);
         SipSessionImpl session = mSessionMap.get(key);
         if ((session != null) && isLoggable(session)) {
-            Log.d(TAG, "session key from event: " + key);
-            Log.d(TAG, "active sessions:");
+            if (DBG) log("getSipSession: event=" + key);
+            if (DBG) log("getSipSession: active sessions:");
             for (String k : mSessionMap.keySet()) {
-                Log.d(TAG, " ..." + k + ": " + mSessionMap.get(k));
+                if (DBG) log("getSipSession: ..." + k + ": " + mSessionMap.get(k));
             }
         }
         return ((session != null) ? session : mCallReceiverSession);
@@ -299,9 +292,9 @@
         String key = newSession.getCallId();
         mSessionMap.put(key, newSession);
         if (isLoggable(newSession)) {
-            Log.d(TAG, "+++  add a session with key:  '" + key + "'");
+            if (DBG) log("addSipSession: key='" + key + "'");
             for (String k : mSessionMap.keySet()) {
-                Log.d(TAG, "  " + k + ": " + mSessionMap.get(k));
+                if (DBG) log("addSipSession:  " + k + ": " + mSessionMap.get(k));
             }
         }
     }
@@ -312,7 +305,7 @@
         SipSessionImpl s = mSessionMap.remove(key);
         // sanity check
         if ((s != null) && (s != session)) {
-            Log.w(TAG, "session " + session + " is not associated with key '"
+            if (DBG) log("removeSession: " + session + " is not associated with key '"
                     + key + "'");
             mSessionMap.put(key, s);
             for (Map.Entry<String, SipSessionImpl> entry
@@ -325,16 +318,17 @@
         }
 
         if ((s != null) && isLoggable(s)) {
-            Log.d(TAG, "remove session " + session + " @key '" + key + "'");
+            if (DBG) log("removeSession: " + session + " @key '" + key + "'");
             for (String k : mSessionMap.keySet()) {
-                Log.d(TAG, "  " + k + ": " + mSessionMap.get(k));
+                if (DBG) log("removeSession:  " + k + ": " + mSessionMap.get(k));
             }
         }
     }
 
+    @Override
     public void processRequest(final RequestEvent event) {
         if (isRequestEvent(Request.INVITE, event)) {
-            if (DEBUG) Log.d(TAG, "<<<<< got INVITE, thread:"
+            if (DBG) log("processRequest: mWakeLock.acquire got INVITE, thread:"
                     + Thread.currentThread());
             // Acquire a wake lock and keep it for WAKE_LOCK_HOLDING_TIME;
             // should be large enough to bring up the app.
@@ -343,22 +337,27 @@
         process(event);
     }
 
+    @Override
     public void processResponse(ResponseEvent event) {
         process(event);
     }
 
+    @Override
     public void processIOException(IOExceptionEvent event) {
         process(event);
     }
 
+    @Override
     public void processTimeout(TimeoutEvent event) {
         process(event);
     }
 
+    @Override
     public void processTransactionTerminated(TransactionTerminatedEvent event) {
         process(event);
     }
 
+    @Override
     public void processDialogTerminated(DialogTerminatedEvent event) {
         process(event);
     }
@@ -369,11 +368,11 @@
             boolean isLoggable = isLoggable(session, event);
             boolean processed = (session != null) && session.process(event);
             if (isLoggable && processed) {
-                Log.d(TAG, "new state after: "
+                log("process: event new state after: "
                         + SipSession.State.toString(session.mState));
             }
         } catch (Throwable e) {
-            Log.w(TAG, "event process error: " + event, getRootCause(e));
+            loge("process: error event=" + event, getRootCause(e));
             session.onError(e);
         }
     }
@@ -404,8 +403,8 @@
         if ((rport > 0) && (externalIp != null)) {
             mExternalIp = externalIp;
             mExternalPort = rport;
-            if (DEBUG) {
-                Log.d(TAG, " got external addr " + externalIp + ":" + rport
+            if (DBG) {
+                log("extractExternalAddress: external addr " + externalIp + ":" + rport
                         + " on " + mSipStack);
             }
         }
@@ -436,6 +435,9 @@
     }
 
     private class SipSessionCallReceiverImpl extends SipSessionImpl {
+        private static final String SSCRI_TAG = "SipSessionCallReceiverImpl";
+        private static final boolean SSCRI_DBG = true;
+
         public SipSessionCallReceiverImpl(ISipSessionListener listener) {
             super(listener);
         }
@@ -473,8 +475,8 @@
             SipSessionImpl newSession = null;
             if (replaces != null) {
                 int response = processInviteWithReplaces(event, replaces);
-                if (DEBUG) {
-                    Log.v(TAG, "ReplacesHeader: " + replaces
+                if (SSCRI_DBG) {
+                    log("processNewInviteRequest: " + replaces
                             + " response=" + response);
                 }
                 if (response == Response.OK) {
@@ -501,10 +503,11 @@
             if (newSession != null) addSipSession(newSession);
         }
 
+        @Override
         public boolean process(EventObject evt) throws SipException {
-            if (isLoggable(this, evt)) Log.d(TAG, " ~~~~~   " + this + ": "
+            if (isLoggable(this, evt)) log("process: " + this + ": "
                     + SipSession.State.toString(mState) + ": processing "
-                    + log(evt));
+                    + logEvt(evt));
             if (isRequestEvent(Request.INVITE, evt)) {
                 processNewInviteRequest((RequestEvent) evt);
                 return true;
@@ -515,6 +518,10 @@
                 return false;
             }
         }
+
+        private void log(String s) {
+            Rlog.d(SSCRI_TAG, s);
+        }
     }
 
     static interface KeepAliveProcessCallback {
@@ -524,6 +531,9 @@
     }
 
     class SipSessionImpl extends ISipSession.Stub {
+        private static final String SSI_TAG = "SipSessionImpl";
+        private static final boolean SSI_DBG = true;
+
         SipProfile mPeerProfile;
         SipSessionListenerProxy mProxy = new SipSessionListenerProxy();
         int mState = SipSession.State.READY_TO_CALL;
@@ -536,9 +546,9 @@
         SessionTimer mSessionTimer;
         int mAuthenticationRetryCount;
 
-        private KeepAliveProcess mKeepAliveProcess;
+        private SipKeepAlive mSipKeepAlive;
 
-        private SipSessionImpl mKeepAliveSession;
+        private SipSessionImpl mSipSessionImpl;
 
         // the following three members are used for handling refer request.
         SipSessionImpl mReferSession;
@@ -551,6 +561,7 @@
 
             void start(final int timeout) {
                 new Thread(new Runnable() {
+                    @Override
                     public void run() {
                         sleep(timeout);
                         if (mRunning) timeout();
@@ -573,7 +584,7 @@
                 try {
                     this.wait(timeout * 1000);
                 } catch (InterruptedException e) {
-                    Log.e(TAG, "session timer interrupted!");
+                    loge("session timer interrupted!", e);
                 }
             }
         }
@@ -617,28 +628,33 @@
 
             cancelSessionTimer();
 
-            if (mKeepAliveSession != null) {
-                mKeepAliveSession.stopKeepAliveProcess();
-                mKeepAliveSession = null;
+            if (mSipSessionImpl != null) {
+                mSipSessionImpl.stopKeepAliveProcess();
+                mSipSessionImpl = null;
             }
         }
 
+        @Override
         public boolean isInCall() {
             return mInCall;
         }
 
+        @Override
         public String getLocalIp() {
             return mLocalIp;
         }
 
+        @Override
         public SipProfile getLocalProfile() {
             return mLocalProfile;
         }
 
+        @Override
         public SipProfile getPeerProfile() {
             return mPeerProfile;
         }
 
+        @Override
         public String getCallId() {
             return SipHelper.getCallId(getTransaction());
         }
@@ -649,10 +665,12 @@
             return null;
         }
 
+        @Override
         public int getState() {
             return mState;
         }
 
+        @Override
         public void setListener(ISipSessionListener listener) {
             mProxy.setListener((listener instanceof SipSessionListenerProxy)
                     ? ((SipSessionListenerProxy) listener).getListener()
@@ -662,11 +680,12 @@
         // process the command in a new thread
         private void doCommandAsync(final EventObject command) {
             new Thread(new Runnable() {
+                    @Override
                     public void run() {
                         try {
                             processCommand(command);
                         } catch (Throwable e) {
-                            Log.w(TAG, "command error: " + command + ": "
+                            loge("command error: " + command + ": "
                                     + mLocalProfile.getUriString(),
                                     getRootCause(e));
                             onError(e);
@@ -675,12 +694,14 @@
             }, "SipSessionAsyncCmdThread").start();
         }
 
+        @Override
         public void makeCall(SipProfile peerProfile, String sessionDescription,
                 int timeout) {
             doCommandAsync(new MakeCallCommand(peerProfile, sessionDescription,
                     timeout));
         }
 
+        @Override
         public void answerCall(String sessionDescription, int timeout) {
             synchronized (SipSessionGroup.this) {
                 if (mPeerProfile == null) return;
@@ -689,10 +710,12 @@
             }
         }
 
+        @Override
         public void endCall() {
             doCommandAsync(END_CALL);
         }
 
+        @Override
         public void changeCall(String sessionDescription, int timeout) {
             synchronized (SipSessionGroup.this) {
                 if (mPeerProfile == null) return;
@@ -701,16 +724,18 @@
             }
         }
 
+        @Override
         public void register(int duration) {
             doCommandAsync(new RegisterCommand(duration));
         }
 
+        @Override
         public void unregister() {
             doCommandAsync(DEREGISTER);
         }
 
         private void processCommand(EventObject command) throws SipException {
-            if (isLoggable(command)) Log.d(TAG, "process cmd: " + command);
+            if (isLoggable(command)) log("process cmd: " + command);
             if (!process(command)) {
                 onError(SipErrorCode.IN_PROGRESS,
                         "cannot initiate a new transaction to execute: "
@@ -723,6 +748,7 @@
             return String.valueOf((long) (Math.random() * 0x100000000L));
         }
 
+        @Override
         public String toString() {
             try {
                 String s = super.toString();
@@ -734,15 +760,15 @@
         }
 
         public boolean process(EventObject evt) throws SipException {
-            if (isLoggable(this, evt)) Log.d(TAG, " ~~~~~   " + this + ": "
+            if (isLoggable(this, evt)) log(" ~~~~~   " + this + ": "
                     + SipSession.State.toString(mState) + ": processing "
-                    + log(evt));
+                    + logEvt(evt));
             synchronized (SipSessionGroup.this) {
                 if (isClosed()) return false;
 
-                if (mKeepAliveProcess != null) {
+                if (mSipKeepAlive != null) {
                     // event consumed by keepalive process
-                    if (mKeepAliveProcess.process(evt)) return true;
+                    if (mSipKeepAlive.process(evt)) return true;
                 }
 
                 Dialog dialog = null;
@@ -824,7 +850,7 @@
             if (mDialog == event.getDialog()) {
                 onError(new SipException("dialog terminated"));
             } else {
-                Log.d(TAG, "not the current dialog; current=" + mDialog
+                if (SSI_DBG) log("not the current dialog; current=" + mDialog
                         + ", terminated=" + event.getDialog());
             }
         }
@@ -838,11 +864,11 @@
                     : event.getClientTransaction();
 
             if ((current != target) && (mState != SipSession.State.PINGING)) {
-                Log.d(TAG, "not the current transaction; current="
+                if (SSI_DBG) log("not the current transaction; current="
                         + toString(current) + ", target=" + toString(target));
                 return false;
             } else if (current != null) {
-                Log.d(TAG, "transaction terminated: " + toString(current));
+                if (SSI_DBG) log("transaction terminated: " + toString(current));
                 return true;
             } else {
                 // no transaction; shouldn't be here; ignored
@@ -865,17 +891,17 @@
             switch (mState) {
                 case SipSession.State.IN_CALL:
                 case SipSession.State.READY_TO_CALL:
-                    Log.d(TAG, "Transaction terminated; do nothing");
+                    if (SSI_DBG) log("Transaction terminated; do nothing");
                     break;
                 default:
-                    Log.d(TAG, "Transaction terminated early: " + this);
+                    if (SSI_DBG) log("Transaction terminated early: " + this);
                     onError(SipErrorCode.TRANSACTION_TERMINTED,
                             "transaction terminated");
             }
         }
 
         private void processTimeout(TimeoutEvent event) {
-            Log.d(TAG, "processing Timeout...");
+            if (SSI_DBG) log("processing Timeout...");
             switch (mState) {
                 case SipSession.State.REGISTERING:
                 case SipSession.State.DEREGISTERING:
@@ -890,7 +916,7 @@
                     break;
 
                 default:
-                    Log.d(TAG, "   do nothing");
+                    if (SSI_DBG) log("   do nothing");
                     break;
             }
         }
@@ -912,8 +938,8 @@
             if (expires != null && time < expires.getExpires()) {
                 time = expires.getExpires();
             }
-            if (DEBUG) {
-                Log.v(TAG, "Expiry time = " + time);
+            if (SSI_DBG) {
+                log("Expiry time = " + time);
             }
             return time;
         }
@@ -960,7 +986,7 @@
                 mDialog = mClientTransaction.getDialog();
                 mAuthenticationRetryCount++;
                 if (isLoggable(this, event)) {
-                    Log.d(TAG, "   authentication retry count="
+                    if (SSI_DBG) log("   authentication retry count="
                             + mAuthenticationRetryCount);
                 }
                 return true;
@@ -984,19 +1010,23 @@
 
         private AccountManager getAccountManager() {
             return new AccountManager() {
+                @Override
                 public UserCredentials getCredentials(ClientTransaction
                         challengedTransaction, String realm) {
                     return new UserCredentials() {
+                        @Override
                         public String getUserName() {
                             String username = mLocalProfile.getAuthUserName();
                             return (!TextUtils.isEmpty(username) ? username :
                                     mLocalProfile.getUserName());
                         }
 
+                        @Override
                         public String getPassword() {
                             return mPassword;
                         }
 
+                        @Override
                         public String getSipDomain() {
                             return mLocalProfile.getSipDomain();
                         }
@@ -1097,8 +1127,7 @@
             return false;
         }
 
-        private boolean incomingCallToInCall(EventObject evt)
-                throws SipException {
+        private boolean incomingCallToInCall(EventObject evt) {
             // expect ACK, CANCEL request
             if (isRequestEvent(Request.ACK, evt)) {
                 String sdp = extractContent(((RequestEvent) evt).getRequest());
@@ -1154,8 +1183,7 @@
                     }
                     return true;
                 case Response.REQUEST_PENDING:
-                    // TODO:
-                    // rfc3261#section-14.1; re-schedule invite
+                    // TODO: rfc3261#section-14.1; re-schedule invite
                     return true;
                 default:
                     if (mReferSession != null) {
@@ -1342,17 +1370,17 @@
         }
 
         private void enableKeepAlive() {
-            if (mKeepAliveSession != null) {
-                mKeepAliveSession.stopKeepAliveProcess();
+            if (mSipSessionImpl != null) {
+                mSipSessionImpl.stopKeepAliveProcess();
             } else {
-                mKeepAliveSession = duplicate();
+                mSipSessionImpl = duplicate();
             }
             try {
-                mKeepAliveSession.startKeepAliveProcess(
+                mSipSessionImpl.startKeepAliveProcess(
                         INCALL_KEEPALIVE_INTERVAL, mPeerProfile, null);
             } catch (SipException e) {
-                Log.w(TAG, "keepalive cannot be enabled; ignored", e);
-                mKeepAliveSession.stopKeepAliveProcess();
+                loge("keepalive cannot be enabled; ignored", e);
+                mSipSessionImpl.stopKeepAliveProcess();
             }
         }
 
@@ -1454,12 +1482,6 @@
             mProxy.onRegistrationFailed(this, errorCode, message);
         }
 
-        private void onRegistrationFailed(Throwable exception) {
-            exception = getRootCause(exception);
-            onRegistrationFailed(getErrorCode(exception),
-                    exception.toString());
-        }
-
         private void onRegistrationFailed(Response response) {
             int statusCode = response.getStatusCode();
             onRegistrationFailed(getErrorCode(statusCode),
@@ -1480,28 +1502,30 @@
         public void startKeepAliveProcess(int interval, SipProfile peerProfile,
                 KeepAliveProcessCallback callback) throws SipException {
             synchronized (SipSessionGroup.this) {
-                if (mKeepAliveProcess != null) {
+                if (mSipKeepAlive != null) {
                     throw new SipException("Cannot create more than one "
                             + "keepalive process in a SipSession");
                 }
                 mPeerProfile = peerProfile;
-                mKeepAliveProcess = new KeepAliveProcess();
-                mProxy.setListener(mKeepAliveProcess);
-                mKeepAliveProcess.start(interval, callback);
+                mSipKeepAlive = new SipKeepAlive();
+                mProxy.setListener(mSipKeepAlive);
+                mSipKeepAlive.start(interval, callback);
             }
         }
 
         public void stopKeepAliveProcess() {
             synchronized (SipSessionGroup.this) {
-                if (mKeepAliveProcess != null) {
-                    mKeepAliveProcess.stop();
-                    mKeepAliveProcess = null;
+                if (mSipKeepAlive != null) {
+                    mSipKeepAlive.stop();
+                    mSipKeepAlive = null;
                 }
             }
         }
 
-        class KeepAliveProcess extends SipSessionAdapter implements Runnable {
-            private static final String TAG = "SipKeepAlive";
+        class SipKeepAlive extends SipSessionAdapter implements Runnable {
+            private static final String SKA_TAG = "SipKeepAlive";
+            private static final boolean SKA_DBG = true;
+
             private boolean mRunning = false;
             private KeepAliveProcessCallback mCallback;
 
@@ -1516,8 +1540,8 @@
                 mInterval = interval;
                 mCallback = new KeepAliveProcessCallbackProxy(callback);
                 mWakeupTimer.set(interval * 1000, this);
-                if (DEBUG) {
-                    Log.d(TAG, "start keepalive:"
+                if (SKA_DBG) {
+                    log("start keepalive:"
                             + mLocalProfile.getUriString());
                 }
 
@@ -1526,7 +1550,7 @@
             }
 
             // return true if the event is consumed
-            boolean process(EventObject evt) throws SipException {
+            boolean process(EventObject evt) {
                 if (mRunning && (mState == SipSession.State.PINGING)) {
                     if (evt instanceof ResponseEvent) {
                         if (parseOptionsResult(evt)) {
@@ -1560,18 +1584,18 @@
                 synchronized (SipSessionGroup.this) {
                     if (!mRunning) return;
 
-                    if (DEBUG_PING) {
+                    if (DBG_PING) {
                         String peerUri = (mPeerProfile == null)
                                 ? "null"
                                 : mPeerProfile.getUriString();
-                        Log.d(TAG, "keepalive: " + mLocalProfile.getUriString()
+                        log("keepalive: " + mLocalProfile.getUriString()
                                 + " --> " + peerUri + ", interval=" + mInterval);
                     }
                     try {
                         sendKeepAlive();
                     } catch (Throwable t) {
-                        if (DEBUG) {
-                            Log.w(TAG, "keepalive error: "
+                        if (SKA_DBG) {
+                            loge("keepalive error: "
                                     + mLocalProfile.getUriString(), getRootCause(t));
                         }
                         // It's possible that the keepalive process is being stopped
@@ -1584,8 +1608,8 @@
 
             void stop() {
                 synchronized (SipSessionGroup.this) {
-                    if (DEBUG) {
-                        Log.d(TAG, "stop keepalive:" + mLocalProfile.getUriString()
+                    if (SKA_DBG) {
+                        log("stop keepalive:" + mLocalProfile.getUriString()
                                 + ",RPort=" + mRPort);
                     }
                     mRunning = false;
@@ -1594,7 +1618,7 @@
                 }
             }
 
-            private void sendKeepAlive() throws SipException, InterruptedException {
+            private void sendKeepAlive() throws SipException {
                 synchronized (SipSessionGroup.this) {
                     mState = SipSession.State.PINGING;
                     mClientTransaction = mSipHelper.sendOptions(
@@ -1615,14 +1639,14 @@
                         if (mRPort == 0) mRPort = rPort;
                         if (mRPort != rPort) {
                             mPortChanged = true;
-                            if (DEBUG) Log.d(TAG, String.format(
+                            if (SKA_DBG) log(String.format(
                                     "rport is changed: %d <> %d", mRPort, rPort));
                             mRPort = rPort;
                         } else {
-                            if (DEBUG) Log.d(TAG, "rport is the same: " + rPort);
+                            if (SKA_DBG) log("rport is the same: " + rPort);
                         }
                     } else {
-                        if (DEBUG) Log.w(TAG, "peer did not respond rport");
+                        if (SKA_DBG) log("peer did not respond rport");
                     }
                     return true;
                 }
@@ -1634,6 +1658,14 @@
                         SIPHeaderNames.VIA));
                 return (viaHeader == null) ? -1 : viaHeader.getRPort();
             }
+
+            private void log(String s) {
+                Rlog.d(SKA_TAG, s);
+            }
+        }
+
+        private void log(String s) {
+            Rlog.d(SSI_TAG, s);
         }
     }
 
@@ -1670,22 +1702,6 @@
         return false;
     }
 
-    /**
-     * @return true if the event is a response event and the response code and
-     *      CSeqHeader method match the given arguments; false otherwise
-     */
-    private static boolean expectResponse(
-            int responseCode, String expectedMethod, EventObject evt) {
-        if (evt instanceof ResponseEvent) {
-            ResponseEvent event = (ResponseEvent) evt;
-            Response response = event.getResponse();
-            if (response.getStatusCode() == responseCode) {
-                return expectedMethod.equalsIgnoreCase(getCseqMethod(response));
-            }
-        }
-        return false;
-    }
-
     private static SipProfile createPeerProfile(HeaderAddress header)
             throws SipException {
         try {
@@ -1710,10 +1726,10 @@
         if (s != null) {
             switch (s.mState) {
                 case SipSession.State.PINGING:
-                    return DEBUG_PING;
+                    return DBG_PING;
             }
         }
-        return DEBUG;
+        return DBG;
     }
 
     private static boolean isLoggable(EventObject evt) {
@@ -1727,19 +1743,19 @@
         if (evt instanceof ResponseEvent) {
             Response response = ((ResponseEvent) evt).getResponse();
             if (Request.OPTIONS.equals(response.getHeader(CSeqHeader.NAME))) {
-                return DEBUG_PING;
+                return DBG_PING;
             }
-            return DEBUG;
+            return DBG;
         } else if (evt instanceof RequestEvent) {
             if (isRequestEvent(Request.OPTIONS, evt)) {
-                return DEBUG_PING;
+                return DBG_PING;
             }
-            return DEBUG;
+            return DBG;
         }
         return false;
     }
 
-    private static String log(EventObject evt) {
+    private static String logEvt(EventObject evt) {
         if (evt instanceof RequestEvent) {
             return ((RequestEvent) evt).getRequest().toString();
         } else if (evt instanceof ResponseEvent) {
@@ -1767,11 +1783,6 @@
         private int mTimeout; // in seconds
 
         public MakeCallCommand(SipProfile peerProfile,
-                String sessionDescription) {
-            this(peerProfile, sessionDescription, -1);
-        }
-
-        public MakeCallCommand(SipProfile peerProfile,
                 String sessionDescription, int timeout) {
             super(peerProfile);
             mSessionDescription = sessionDescription;
@@ -1793,6 +1804,7 @@
 
     /** Class to help safely run KeepAliveProcessCallback in a different thread. */
     static class KeepAliveProcessCallbackProxy implements KeepAliveProcessCallback {
+        private static final String KAPCP_TAG = "KeepAliveProcessCallbackProxy";
         private KeepAliveProcessCallback mCallback;
 
         KeepAliveProcessCallbackProxy(KeepAliveProcessCallback callback) {
@@ -1806,30 +1818,46 @@
             new Thread(runnable, "SIP-KeepAliveProcessCallbackThread").start();
         }
 
+        @Override
         public void onResponse(final boolean portChanged) {
             if (mCallback == null) return;
             proxy(new Runnable() {
+                @Override
                 public void run() {
                     try {
                         mCallback.onResponse(portChanged);
                     } catch (Throwable t) {
-                        Log.w(TAG, "onResponse", t);
+                        loge("onResponse", t);
                     }
                 }
             });
         }
 
+        @Override
         public void onError(final int errorCode, final String description) {
             if (mCallback == null) return;
             proxy(new Runnable() {
+                @Override
                 public void run() {
                     try {
                         mCallback.onError(errorCode, description);
                     } catch (Throwable t) {
-                        Log.w(TAG, "onError", t);
+                        loge("onError", t);
                     }
                 }
             });
         }
+
+        private void loge(String s, Throwable t) {
+            Rlog.e(KAPCP_TAG, s, t);
+        }
+    }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
+    }
+
+    private void loge(String s, Throwable t) {
+        Rlog.e(TAG, s, t);
     }
 }
diff --git a/voip/java/com/android/server/sip/SipSessionListenerProxy.java b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
index 8655a3a..7a4ae8d 100644
--- a/voip/java/com/android/server/sip/SipSessionListenerProxy.java
+++ b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
@@ -20,11 +20,11 @@
 import android.net.sip.ISipSessionListener;
 import android.net.sip.SipProfile;
 import android.os.DeadObjectException;
-import android.util.Log;
+import android.telephony.Rlog;
 
 /** Class to help safely run a callback in a different thread. */
 class SipSessionListenerProxy extends ISipSessionListener.Stub {
-    private static final String TAG = "SipSession";
+    private static final String TAG = "SipSessionListnerProxy";
 
     private ISipSessionListener mListener;
 
@@ -43,9 +43,11 @@
         new Thread(runnable, "SipSessionCallbackThread").start();
     }
 
+    @Override
     public void onCalling(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onCalling(session);
@@ -56,10 +58,12 @@
         });
     }
 
+    @Override
     public void onRinging(final ISipSession session, final SipProfile caller,
             final String sessionDescription) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onRinging(session, caller, sessionDescription);
@@ -70,9 +74,11 @@
         });
     }
 
+    @Override
     public void onRingingBack(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onRingingBack(session);
@@ -83,10 +89,12 @@
         });
     }
 
+    @Override
     public void onCallEstablished(final ISipSession session,
             final String sessionDescription) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onCallEstablished(session, sessionDescription);
@@ -97,9 +105,11 @@
         });
     }
 
+    @Override
     public void onCallEnded(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onCallEnded(session);
@@ -110,10 +120,12 @@
         });
     }
 
+    @Override
     public void onCallTransferring(final ISipSession newSession,
             final String sessionDescription) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onCallTransferring(newSession, sessionDescription);
@@ -124,9 +136,11 @@
         });
     }
 
+    @Override
     public void onCallBusy(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onCallBusy(session);
@@ -137,10 +151,12 @@
         });
     }
 
+    @Override
     public void onCallChangeFailed(final ISipSession session,
             final int errorCode, final String message) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onCallChangeFailed(session, errorCode, message);
@@ -151,10 +167,12 @@
         });
     }
 
+    @Override
     public void onError(final ISipSession session, final int errorCode,
             final String message) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onError(session, errorCode, message);
@@ -165,9 +183,11 @@
         });
     }
 
+    @Override
     public void onRegistering(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onRegistering(session);
@@ -178,10 +198,12 @@
         });
     }
 
+    @Override
     public void onRegistrationDone(final ISipSession session,
             final int duration) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onRegistrationDone(session, duration);
@@ -192,10 +214,12 @@
         });
     }
 
+    @Override
     public void onRegistrationFailed(final ISipSession session,
             final int errorCode, final String message) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onRegistrationFailed(session, errorCode, message);
@@ -206,9 +230,11 @@
         });
     }
 
+    @Override
     public void onRegistrationTimeout(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onRegistrationTimeout(session);
@@ -225,7 +251,15 @@
             // This creates race but it's harmless. Just don't log the error
             // when it happens.
         } else if (mListener != null) {
-            Log.w(TAG, message, t);
+            loge(message, t);
         }
     }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
+    }
+
+    private void loge(String s, Throwable t) {
+        Rlog.e(TAG, s, t);
+    }
 }
diff --git a/voip/java/com/android/server/sip/SipWakeLock.java b/voip/java/com/android/server/sip/SipWakeLock.java
index 0c4d14c..b3fbb56 100644
--- a/voip/java/com/android/server/sip/SipWakeLock.java
+++ b/voip/java/com/android/server/sip/SipWakeLock.java
@@ -17,13 +17,13 @@
 package com.android.server.sip;
 
 import android.os.PowerManager;
-import android.util.Log;
+import android.telephony.Rlog;
 
 import java.util.HashSet;
 
 class SipWakeLock {
-    private static final boolean DEBUG = false;
     private static final String TAG = "SipWakeLock";
+    private static final boolean DBG = false;
     private PowerManager mPowerManager;
     private PowerManager.WakeLock mWakeLock;
     private PowerManager.WakeLock mTimerWakeLock;
@@ -34,7 +34,7 @@
     }
 
     synchronized void reset() {
-        if (DEBUG) Log.v(TAG, "reset count=" + mHolders.size());
+        if (DBG) log("reset count=" + mHolders.size());
         mHolders.clear();
         release(null);
     }
@@ -55,7 +55,7 @@
                     PowerManager.PARTIAL_WAKE_LOCK, "SipWakeLock");
         }
         if (!mWakeLock.isHeld()) mWakeLock.acquire();
-        if (DEBUG) Log.v(TAG, "acquire count=" + mHolders.size());
+        if (DBG) log("acquire count=" + mHolders.size());
     }
 
     synchronized void release(Object holder) {
@@ -64,6 +64,10 @@
                 && mWakeLock.isHeld()) {
             mWakeLock.release();
         }
-        if (DEBUG) Log.v(TAG, "release count=" + mHolders.size());
+        if (DBG) log("release count=" + mHolders.size());
+    }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
     }
 }
diff --git a/voip/java/com/android/server/sip/SipWakeupTimer.java b/voip/java/com/android/server/sip/SipWakeupTimer.java
index 00d47ac..3ba43312 100644
--- a/voip/java/com/android/server/sip/SipWakeupTimer.java
+++ b/voip/java/com/android/server/sip/SipWakeupTimer.java
@@ -23,31 +23,20 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.SystemClock;
-import android.util.Log;
+import android.telephony.Rlog;
 
-import java.io.IOException;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Comparator;
-import java.util.HashMap;
 import java.util.Iterator;
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
 import java.util.TreeSet;
 import java.util.concurrent.Executor;
-import javax.sip.SipException;
 
 /**
  * Timer that can schedule events to occur even when the device is in sleep.
  */
 class SipWakeupTimer extends BroadcastReceiver {
-    private static final String TAG = "_SIP.WkTimer_";
+    private static final String TAG = "SipWakeupTimer";
+    private static final boolean DBG = SipService.DBG && true; // STOPSHIP if true
     private static final String TRIGGER_TIME = "TriggerTime";
-    private static final boolean DEBUG_TIMER = SipService.DEBUG && false;
 
     private Context mContext;
     private AlarmManager mAlarmManager;
@@ -85,7 +74,7 @@
 
     private boolean stopped() {
         if (mEventQueue == null) {
-            Log.w(TAG, "Timer stopped");
+            if (DBG) log("Timer stopped");
             return true;
         } else {
             return false;
@@ -112,11 +101,11 @@
         }
         TreeSet<MyEvent> newQueue = new TreeSet<MyEvent>(
                 mEventQueue.comparator());
-        newQueue.addAll((Collection<MyEvent>) mEventQueue);
+        newQueue.addAll(mEventQueue);
         mEventQueue.clear();
         mEventQueue = newQueue;
-        if (DEBUG_TIMER) {
-            Log.d(TAG, "queue re-calculated");
+        if (DBG) {
+            log("queue re-calculated");
             printQueue();
         }
     }
@@ -172,8 +161,8 @@
         }
 
         long triggerTime = event.mTriggerTime;
-        if (DEBUG_TIMER) {
-            Log.d(TAG, " add event " + event + " scheduled on "
+        if (DBG) {
+            log("set: add event " + event + " scheduled on "
                     + showTime(triggerTime) + " at " + showTime(now)
                     + ", #events=" + mEventQueue.size());
             printQueue();
@@ -187,7 +176,7 @@
      */
     public synchronized void cancel(Runnable callback) {
         if (stopped() || mEventQueue.isEmpty()) return;
-        if (DEBUG_TIMER) Log.d(TAG, "cancel:" + callback);
+        if (DBG) log("cancel:" + callback);
 
         MyEvent firstEvent = mEventQueue.first();
         for (Iterator<MyEvent> iter = mEventQueue.iterator();
@@ -195,7 +184,7 @@
             MyEvent event = iter.next();
             if (event.mCallback == callback) {
                 iter.remove();
-                if (DEBUG_TIMER) Log.d(TAG, "    cancel found:" + event);
+                if (DBG) log("    cancel found:" + event);
             }
         }
         if (mEventQueue.isEmpty()) {
@@ -209,8 +198,8 @@
             recalculatePeriods();
             scheduleNext();
         }
-        if (DEBUG_TIMER) {
-            Log.d(TAG, "after cancel:");
+        if (DBG) {
+            log("cancel: X");
             printQueue();
         }
     }
@@ -242,33 +231,33 @@
             long triggerTime = intent.getLongExtra(TRIGGER_TIME, -1L);
             execute(triggerTime);
         } else {
-            Log.d(TAG, "unrecognized intent: " + intent);
+            log("onReceive: unrecognized intent: " + intent);
         }
     }
 
     private void printQueue() {
         int count = 0;
         for (MyEvent event : mEventQueue) {
-            Log.d(TAG, "     " + event + ": scheduled at "
+            log("     " + event + ": scheduled at "
                     + showTime(event.mTriggerTime) + ": last at "
                     + showTime(event.mLastTriggerTime));
             if (++count >= 5) break;
         }
         if (mEventQueue.size() > count) {
-            Log.d(TAG, "     .....");
+            log("     .....");
         } else if (count == 0) {
-            Log.d(TAG, "     <empty>");
+            log("     <empty>");
         }
     }
 
     private void execute(long triggerTime) {
-        if (DEBUG_TIMER) Log.d(TAG, "time's up, triggerTime = "
+        if (DBG) log("time's up, triggerTime = "
                 + showTime(triggerTime) + ": " + mEventQueue.size());
         if (stopped() || mEventQueue.isEmpty()) return;
 
         for (MyEvent event : mEventQueue) {
             if (event.mTriggerTime != triggerTime) continue;
-            if (DEBUG_TIMER) Log.d(TAG, "execute " + event);
+            if (DBG) log("execute " + event);
 
             event.mLastTriggerTime = triggerTime;
             event.mTriggerTime += event.mPeriod;
@@ -276,8 +265,8 @@
             // run the callback in the handler thread to prevent deadlock
             mExecutor.execute(event.mCallback);
         }
-        if (DEBUG_TIMER) {
-            Log.d(TAG, "after timeout execution");
+        if (DBG) {
+            log("after timeout execution");
             printQueue();
         }
         scheduleNext();
@@ -327,6 +316,7 @@
     // Sort the events by mMaxPeriod so that the first event can be used to
     // align events with larger periods
     private static class MyEventComparator implements Comparator<MyEvent> {
+        @Override
         public int compare(MyEvent e1, MyEvent e2) {
             if (e1 == e2) return 0;
             int diff = e1.mMaxPeriod - e2.mMaxPeriod;
@@ -334,8 +324,13 @@
             return diff;
         }
 
+        @Override
         public boolean equals(Object that) {
             return (this == that);
         }
     }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
+    }
 }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 55de065..0be453c 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -45,7 +45,7 @@
 
     void startScan(boolean forceActive);
 
-    List<ScanResult> getScanResults();
+    List<ScanResult> getScanResults(String callingPackage);
 
     void disconnect();
 
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index ac53eb2..66c2f3f 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -1089,17 +1089,19 @@
                 break setVariables;
             }
 
-            HashMap<String, String> enterpriseFields = config.enterpriseConfig.getFields();
-            for (String key : enterpriseFields.keySet()) {
-                    String value = enterpriseFields.get(key);
-                    if (!mWifiNative.setNetworkVariable(
-                                netId,
-                                key,
-                                value)) {
-                        loge(config.SSID + ": failed to set " + key +
-                                ": " + value);
-                        break setVariables;
-                    }
+            if (config.enterpriseConfig != null) {
+                HashMap<String, String> enterpriseFields = config.enterpriseConfig.getFields();
+                for (String key : enterpriseFields.keySet()) {
+                        String value = enterpriseFields.get(key);
+                        if (!mWifiNative.setNetworkVariable(
+                                    netId,
+                                    key,
+                                    value)) {
+                            loge(config.SSID + ": failed to set " + key +
+                                    ": " + value);
+                            break setVariables;
+                        }
+                }
             }
             updateFailed = false;
         }
@@ -1398,11 +1400,16 @@
             }
         }
 
-        HashMap<String, String> entepriseFields = config.enterpriseConfig.getFields();
-        for (String key : entepriseFields.keySet()) {
+        if (config.enterpriseConfig == null) {
+            config.enterpriseConfig = new WifiEnterpriseConfig();
+        }
+        HashMap<String, String> enterpriseFields = config.enterpriseConfig.getFields();
+        for (String key : WifiEnterpriseConfig.getSupplicantKeys()) {
             value = mWifiNative.getNetworkVariable(netId, key);
             if (!TextUtils.isEmpty(value)) {
-                entepriseFields.put(key, removeDoubleQuotes(value));
+                enterpriseFields.put(key, removeDoubleQuotes(value));
+            } else {
+                enterpriseFields.put(key, WifiEnterpriseConfig.EMPTY_VALUE);
             }
         }
 
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 46e446e..4dca7ac 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -74,18 +74,14 @@
     /** This represents an empty value of an enterprise field.
      * NULL is used at wpa_supplicant to indicate an empty value
      */
-    private static final String EMPTY_VALUE = "NULL";
+    static final String EMPTY_VALUE = "NULL";
 
     public WifiEnterpriseConfig() {
-        // Set the required defaults
-        mFields.put(EAP_KEY, Eap.strings[Eap.PEAP]);
-        mFields.put(ENGINE_KEY, ENGINE_DISABLE);
+        // Do not set defaults so that the enterprise fields that are not changed
+        // by API are not changed underneath
+        // This is essential because an app may not have all fields like password
+        // available. It allows modification of subset of fields.
 
-        for (String key : new String[] {PHASE2_KEY, IDENTITY_KEY, ANON_IDENTITY_KEY,
-                PASSWORD_KEY, CLIENT_CERT_KEY, ENGINE_ID_KEY, PRIVATE_KEY_ID_KEY,
-                CA_CERT_KEY, SUBJECT_MATCH_KEY}) {
-            mFields.put(key, EMPTY_VALUE);
-        }
     }
 
     /** Copy constructor */
@@ -128,6 +124,8 @@
             };
 
     public static final class Eap {
+        /* NONE represents an empty enterprise config */
+        public static final int NONE    = -1;
         public static final int PEAP    = 0;
         public static final int TLS     = 1;
         public static final int TTLS    = 2;
@@ -152,6 +150,13 @@
         return mFields;
     }
 
+    /** Internal use only @hide */
+    public static String[] getSupplicantKeys() {
+        return new String[] { EAP_KEY, PHASE2_KEY, IDENTITY_KEY, ANON_IDENTITY_KEY, PASSWORD_KEY,
+                CLIENT_CERT_KEY, CA_CERT_KEY, SUBJECT_MATCH_KEY, ENGINE_KEY, ENGINE_ID_KEY,
+                PRIVATE_KEY_ID_KEY };
+    }
+
     /**
      * Set the EAP authentication method.
      * @param  eapMethod is one {@link Eap#PEAP}, {@link Eap#TLS}, {@link Eap#TTLS} or
@@ -177,7 +182,7 @@
      */
     public int getEapMethod() {
         String eapMethod  = mFields.get(EAP_KEY);
-        return getStringIndex(Eap.strings, eapMethod, Eap.PEAP);
+        return getStringIndex(Eap.strings, eapMethod, Eap.NONE);
     }
 
     /**
@@ -211,7 +216,11 @@
      * @return a phase 2 method defined at {@link Phase2}
      * */
     public int getPhase2Method() {
-        String phase2Method = mFields.get(PHASE2_KEY);
+        String phase2Method = removeDoubleQuotes(mFields.get(PHASE2_KEY));
+        // Remove auth= prefix
+        if (phase2Method.startsWith(Phase2.PREFIX)) {
+            phase2Method = phase2Method.substring(Phase2.PREFIX.length());
+        }
         return getStringIndex(Phase2.strings, phase2Method, Phase2.NONE);
     }
 
@@ -387,9 +396,7 @@
      */
     private int getStringIndex(String arr[], String toBeFound, int defaultIndex) {
         for (int i = 0; i < arr.length; i++) {
-            // toBeFound can be formatted with a prefix. For example, phase2
-            // string has "auth=" as the prefix.
-            if (toBeFound.contains(arr[i])) return i;
+            if (toBeFound.equals(arr[i])) return i;
         }
         return defaultIndex;
     }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4861759..c08db07 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -777,7 +777,7 @@
      */
     public List<ScanResult> getScanResults() {
         try {
-            return mService.getScanResults();
+            return mService.getScanResults(mContext.getBasePackageName());
         } catch (RemoteException e) {
             return null;
         }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 0a61972..476ebbc 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -2315,7 +2315,7 @@
             if (!mWifiNative.setSerialNumber(detail)) {
                 loge("Failed to set serial number " + detail);
             }
-            if (!mWifiNative.setConfigMethods("physical_display virtual_push_button keypad")) {
+            if (!mWifiNative.setConfigMethods("physical_display virtual_push_button")) {
                 loge("Failed to set WPS config methods");
             }
             if (!mWifiNative.setDeviceType(mPrimaryDeviceType)) {